FORM  4.1
minos.c
Go to the documentation of this file.
1 
7 /* #[ License : */
8 /*
9  * Copyright (C) 1984-2013 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  for ( ; i < numblocks; i++ ) {
977  if ( ( d->nblocks[i] = (NAMESBLOCK *)Malloc1(sizeof(NAMESBLOCK),
978  "additional names blocks ") ) == 0 ) {
979  FreeTableBase(d);
980  return(-1);
981  }
982  d->nblocks[i]->previousblock = -1;
983  d->nblocks[i]->position = -1;
984  s = d->nblocks[i]->names;
985  for ( j = 0; j < NAMETABLESIZE; j++ ) *s++ = 0;
986  }
987  d->info.numberofnamesblocks = numblocks;
988  }
989 /*
990  Now look till where the new contents agree with the old.
991 */
992  firstdif = 0;
993  i = 0; t = d->nblocks[i]->names; j = 0; s = d->tablenames;
994  for ( m = 0; m < d->tablenamefill; m++ ) {
995  if ( *s == *t ) {
996  s++; t++; j++;
997  if ( j >= NAMETABLESIZE ) {
998  i++;
999  t = d->nblocks[i]->names;
1000  j = 0;
1001  }
1002  }
1003  else {
1004  firstdif = i;
1005  for ( ; m < d->tablenamefill; m++ ) {
1006  *t++ = *s++; j++;
1007  }
1008  if ( j >= NAMETABLESIZE ) {
1009  i++;
1010  t = d->nblocks[i]->names;
1011  j = 0;
1012  }
1013  *t = 0;
1014  break;
1015  }
1016  }
1017  for ( i = 0; i < d->info.numberofnamesblocks; i++ ) {
1018  if ( i == firstdif ) break;
1019  if ( d->nblocks[i]->position < 0 ) { firstdif = i; break; }
1020  }
1021 /*
1022  Now we have to (re)write the blocks, starting at firstdif.
1023 */
1024  for ( i = firstdif; i < d->info.numberofnamesblocks; i++ ) {
1025  if ( i > 0 ) d->nblocks[i]->previousblock = d->nblocks[i-1]->position;
1026  else d->nblocks[i]->previousblock = -1;
1027  if ( d->nblocks[i]->position < 0 ) {
1028  fseek(d->handle,0,SEEK_END);
1029  d->nblocks[i]->position = ftell(d->handle);
1030  }
1031  else fseek(d->handle,d->nblocks[i]->position,SEEK_SET);
1032  convertnamesblock(d->nblocks[i],&scratchnamesblock,TODISK);
1033  if ( minoswrite(d->handle,(char *)(&scratchnamesblock),sizeof(NAMESBLOCK)) ) {
1034  MesPrint("Error while writing names blocks\n");
1035  FreeTableBase(d);
1036  return(-1);
1037  }
1038  }
1039  d->info.lastnameblock = d->nblocks[d->info.numberofnamesblocks-1]->position;
1040  d->info.firstnameblock = d->nblocks[0]->position;
1041  return(WriteIniInfo(d));
1042 }
1043 
1044 /*
1045  #] PutTableNames :
1046  #[ AddToIndex :
1047 */
1048 
1049 int AddToIndex(DBASE *d,MLONG number)
1050 {
1051  MLONG i, oldnumofindexblocks = d->info.numberofindexblocks;
1052  MLONG j, newnumofindexblocks, jj;
1053  INDEXBLOCK **ib;
1054  MLONG t = (MLONG)(time(0));
1055  if ( number == 0 ) return(0);
1056  else if ( number < 0 ) {
1057  if ( d->info.entriesinindex < -number ) {
1058  MesPrint("There are only %ld entries in the index of file %s\n",
1059  d->info.entriesinindex,d->name);
1060  return(-1);
1061  }
1062  d->info.entriesinindex += number;
1063 dowrite:
1064  if ( WriteIniInfo(d) ) {
1065  d->info.entriesinindex -= number;
1066  MesPrint("File may be corrupted\n");
1067  return(-1);
1068  }
1069  }
1070  else if ( d->info.entriesinindex+number <=
1071  NUMOBJECTS*d->info.numberofindexblocks ) {
1072  d->info.entriesinindex += number;
1073  goto dowrite;
1074  }
1075  else {
1076  d->info.entriesinindex += number;
1077  newnumofindexblocks = d->info.numberofindexblocks + ((number -
1078  (NUMOBJECTS*d->info.numberofindexblocks - d->info.entriesinindex))
1079  +NUMOBJECTS-1)/NUMOBJECTS;
1080  if ( ( ib = (INDEXBLOCK **)Malloc1(sizeof(INDEXBLOCK *)*newnumofindexblocks,
1081  "index") ) == 0 ) return(-1);
1082  for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
1083  ib[i] = d->iblocks[i];
1084  }
1085  for ( i = d->info.numberofindexblocks; i < newnumofindexblocks; i++ ) {
1086  if ( ( ib[i] = (INDEXBLOCK *)Malloc1(sizeof(INDEXBLOCK),"index block") ) == 0 ) {
1087  FreeTableBase(d);
1088  return(-1);
1089  }
1090  if ( i > 0 ) ib[i]->previousblock = ib[i-1]->position;
1091  else ib[i]->previousblock = -1;
1092 /*
1093  Zero things properly. We don't want garbage in the file.
1094 */
1095  for ( j = 0; j < NUMOBJECTS; j++ ) {
1096  ib[i]->objects[j].date = t;
1097  ib[i]->objects[j].size = 0;
1098  ib[i]->objects[j].position = -1;
1099  ib[i]->objects[j].tablenumber = 0;
1100  ib[i]->objects[j].uncompressed = 0;
1101  ib[i]->objects[j].spare1 = 0;
1102  ib[i]->objects[j].spare2 = 0;
1103  ib[i]->objects[j].spare3 = 0;
1104  for ( jj = 0; jj < ELEMENTSIZE; jj++ ) ib[i]->objects[j].element[jj] = 0;
1105  }
1106  fseek(d->handle,0,SEEK_END);
1107  ib[i]->position = ftell(d->handle);
1108  convertblock(ib[i],&scratchblock,TODISK);
1109  if ( minoswrite(d->handle,(char *)(&scratchblock),sizeof(INDEXBLOCK)) ) {
1110  MesPrint("Error while writing new index of file %s",d->name);
1111  FreeTableBase(d);
1112  return(-1);
1113  }
1114  }
1115  d->info.lastindexblock = ib[newnumofindexblocks-1]->position;
1116  d->info.firstindexblock = ib[0]->position;
1117  d->info.numberofindexblocks = newnumofindexblocks;
1118  if ( WriteIniInfo(d) ) {
1119  d->info.numberofindexblocks = oldnumofindexblocks;
1120  d->info.entriesinindex -= number;
1121  MesPrint("File may be corrupted\n");
1122  FreeTableBase(d);
1123  return(-1);
1124  }
1125  M_free(d->iblocks,"AddToIndex");
1126  d->iblocks = ib;
1127  }
1128  return(0);
1129 }
1130 
1131 /*
1132  #] AddToIndex :
1133  #[ AddObject :
1134 */
1135 
1136 MLONG AddObject(DBASE *d,MLONG tablenumber,char *arguments,char *rhs)
1137 {
1138  MLONG number;
1139  number = d->info.entriesinindex;
1140  if ( AddToIndex(d,1) ) return(-1);
1141  if ( WriteObject(d,tablenumber,arguments,rhs,number) ) return(-1);
1142  return(number);
1143 }
1144 
1145 /*
1146  #] AddObject :
1147  #[ FindTableNumber :
1148 */
1149 
1150 MLONG FindTableNumber(DBASE *d,char *name)
1151 {
1152  char *s = d->tablenames, *t, *ss;
1153  MLONG num = 0;
1154  ss = d->tablenames + d->tablenamefill;
1155  while ( s < ss ) {
1156  num++;
1157  t = name;
1158  while ( *s == *t && *t ) {
1159  s++; t++;
1160  }
1161  if ( *s == 0 && *t == 0 ) return(num);
1162  while ( *s ) s++;
1163  s++;
1164 /*
1165  Skip also the argument tail
1166 */
1167  while ( *s ) s++;
1168  s++;
1169  }
1170  return(-1); /* Name not found */
1171 }
1172 
1173 /*
1174  #] FindTableNumber :
1175  #[ WriteObject :
1176 */
1177 
1178 int WriteObject(DBASE *d,MLONG tablenumber,char *arguments,char *rhs,MLONG number)
1179 {
1180  char *s, *a;
1181 #ifdef WITHZLIB
1182  char *buffer = 0;
1183  uLongf newsize = 0, oldsize = 0;
1184  uLong ssize;
1185  int error = 0;
1186 #endif
1187  MLONG i, j, position, size, n;
1188  OBJECTS *obj;
1189  if ( ( d->mode & INPUTONLY ) == INPUTONLY ) {
1190  MesPrint("Not allowed to write to input\n");
1191  return(-1);
1192  }
1193  if ( number >= d->info.entriesinindex ) {
1194  MesPrint("Reference to non-existing object number %ld\n",number+1);
1195  return(0);
1196  }
1197  j = number/NUMOBJECTS;
1198  i = number%NUMOBJECTS;
1199  obj = &(d->iblocks[j]->objects[i]);
1200  a = arguments;
1201  while ( *a ) a++;
1202  a++; n = a - arguments;
1203  if ( n > ELEMENTSIZE ) {
1204  MesPrint("Table element %s has more than %ld characters.\n",arguments,
1205  (MLONG)ELEMENTSIZE);
1206  return(-1);
1207  }
1208  s = obj->element;
1209  a = arguments;
1210  while ( *a ) *s++ = *a++;
1211  *s++ = 0;
1212  while ( n < ELEMENTSIZE ) { *s++ = 0; n++; }
1213  obj->spare1 = obj->spare2 = obj->spare3 = 0;
1214 
1215  fseek(d->handle,0,SEEK_END);
1216  position = ftell(d->handle);
1217  s = rhs;
1218  while ( *s ) s++;
1219  s++;
1220  size = s - rhs;
1221 #ifdef WITHZLIB
1222  if ( ( d->mode & NOCOMPRESS ) == 0 ) {
1223  newsize = size + size/1000 + 20;
1224  if ( ( buffer = (char *)Malloc1(newsize*sizeof(char),"compress buffer") )
1225  == 0 ) {
1226  MesPrint("No compress used for element %s in file %s\n",arguments,d->name);
1227  }
1228  }
1229  else buffer = 0;
1230  if ( buffer ) {
1231  ssize = size;
1232  if ( ( error = compress((Bytef *)buffer,&newsize,(Bytef *)rhs,ssize) ) != Z_OK ) {
1233  MesPrint("Error = %d\n",error);
1234  MesPrint("Due to error no compress used for element %s in file %s\n",arguments,d->name);
1235  M_free(buffer,"tb,WriteObject");
1236  buffer = 0;
1237  }
1238  }
1239  if ( buffer ) {
1240  rhs = buffer;
1241  oldsize = size;
1242  size = newsize;
1243  }
1244 #endif
1245  if ( minoswrite(d->handle,rhs,size) ) {
1246  MesPrint("Error while writing rhs\n");
1247  return(-1);
1248  }
1249  obj->position = position;
1250  obj->size = size;
1251  obj->date = (MLONG)(time(0));
1252  obj->tablenumber = tablenumber;
1253 #ifdef WITHZLIB
1254  obj->uncompressed = oldsize;
1255  if ( buffer ) M_free(buffer,"tb,WriteObject");
1256 #else
1257  obj->uncompressed = 0;
1258 #endif
1259  return(WriteIndexBlock(d,j));
1260 }
1261 
1262 /*
1263  #] WriteObject :
1264  #[ ReadObject :
1265 
1266  Returns a pointer to the proper rhs
1267 */
1268 
1269 char *ReadObject(DBASE *d,MLONG tablenumber,char *arguments)
1270 {
1271  OBJECTS *obj;
1272  MLONG i, j;
1273  char *buffer1, *s, *t;
1274 #ifdef WITHZLIB
1275  char *buffer2 = 0;
1276  uLongf finallength = 0;
1277 #endif
1278  if ( tablenumber > d->topnumber ) {
1279  MesPrint("Reference to non-existing table number in tablebase %s: %ld\n",
1280  d->name,tablenumber);
1281  return(0);
1282  }
1283 /*
1284  Start looking for the object
1285 */
1286  for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
1287  for ( j = 0; j < NUMOBJECTS; j++ ) {
1288  if ( d->iblocks[i]->objects[j].tablenumber != tablenumber ) continue;
1289  s = arguments; t = d->iblocks[i]->objects[j].element;
1290  while ( *s == *t && *s ) { s++; t++; }
1291  if ( *t == 0 && *s == 0 ) goto foundelement;
1292  }
1293  }
1294  s = d->tablenames; i = 1;
1295  while ( *s ) {
1296  if ( i == tablenumber ) break;
1297  while ( *s ) s++; s++;
1298  while ( *s ) s++; s++;
1299  i++;
1300  }
1301  MesPrint("%s(%s) not found in tablebase %s\n",s,arguments,d->name);
1302  return(0);
1303 
1304 foundelement:;
1305  obj = &(d->iblocks[i]->objects[j]);
1306  fseek(d->handle,obj->position,SEEK_SET);
1307  if ( ( buffer1 = (char *)Malloc1(obj->size,"reading rhs buffer1") ) == 0 ) {
1308  return(0);
1309  }
1310 #ifdef WITHZLIB
1311  if ( obj->uncompressed > 0 ) {
1312  if ( ( buffer2 = (char *)Malloc1(obj->uncompressed,"reading rhs buffer2") ) == 0 ) {
1313  return(0);
1314  }
1315  }
1316  else buffer2 = 0;
1317 #endif
1318  if ( minosread(d->handle,buffer1,obj->size) ) {
1319  MesPrint("Could not read rhs %s in file %s\n",arguments,d->name);
1320  M_free(buffer1,"tb,ReadObject");
1321 #ifdef WITHZLIB
1322  if ( buffer2 ) M_free(buffer2,"tb,ReadObject");
1323 #endif
1324  return(0);
1325  }
1326 #ifdef WITHZLIB
1327  if ( buffer2 == 0 ) return(buffer1);
1328  finallength = obj->uncompressed;
1329  if ( uncompress((Bytef *)buffer2,&finallength,(Bytef *)buffer1,obj->size) != Z_OK ) {
1330  MesPrint("Cannot uncompress element %s in file %s\n",arguments,d->name);
1331  M_free(buffer1,"tb,ReadObject"); M_free(buffer2,"tb,ReadObject");
1332  return(0);
1333  }
1334  M_free(buffer1,"tb,ReadObject");
1335  return(buffer2);
1336 #else
1337  return(buffer1);
1338 #endif
1339 }
1340 
1341 /*
1342  #] ReadObject :
1343  #[ ReadijObject :
1344 
1345  Returns a pointer to the proper rhs
1346 */
1347 
1348 char *ReadijObject(DBASE *d,MLONG i,MLONG j,char *arguments)
1349 {
1350  OBJECTS *obj;
1351  char *buffer1;
1352 #ifdef WITHZLIB
1353  char *buffer2 = 0;
1354  uLongf finallength = 0;
1355 #endif
1356  obj = &(d->iblocks[i]->objects[j]);
1357  fseek(d->handle,obj->position,SEEK_SET);
1358  if ( ( buffer1 = (char *)Malloc1(obj->size,"reading rhs buffer1") ) == 0 ) {
1359  return(0);
1360  }
1361 #ifdef WITHZLIB
1362  if ( obj->uncompressed > 0 ) {
1363  if ( ( buffer2 = (char *)Malloc1(obj->uncompressed,"reading rhs buffer2") ) == 0 ) {
1364  return(0);
1365  }
1366  }
1367  else buffer2 = 0;
1368 #endif
1369  if ( minosread(d->handle,buffer1,obj->size) ) {
1370  MesPrint("Could not read rhs %s in file %s\n",arguments,d->name);
1371  if ( buffer1 ) M_free(buffer1,"rhs buffer1");
1372 #ifdef WITHZLIB
1373  if ( buffer2 ) M_free(buffer2,"rhs buffer2");
1374 #endif
1375  return(0);
1376  }
1377 #ifdef WITHZLIB
1378  if ( buffer2 == 0 ) return(buffer1);
1379  finallength = obj->uncompressed;
1380  if ( uncompress((Bytef *)buffer2,&finallength,(Bytef *)buffer1,obj->size) != Z_OK ) {
1381  MesPrint("Cannot uncompress element %s in file %s\n",arguments,d->name);
1382  if ( buffer1 ) M_free(buffer1,"rhs buffer1");
1383  if ( buffer2 ) M_free(buffer2,"rhs buffer2");
1384  return(0);
1385  }
1386  M_free(buffer1,"rhs buffer1");
1387  return(buffer2);
1388 #else
1389  return(buffer1);
1390 #endif
1391 }
1392 
1393 /*
1394  #] ReadijObject :
1395  #[ ExistsObject :
1396 
1397  Returns 1 if Object exists
1398 */
1399 
1400 int ExistsObject(DBASE *d,MLONG tablenumber,char *arguments)
1401 {
1402  MLONG i, j;
1403  char *s, *t;
1404  if ( tablenumber > d->topnumber ) {
1405  MesPrint("Reference to non-existing table number in tablebase %s: %ld\n",
1406  d->name,tablenumber);
1407  return(0);
1408  }
1409 /*
1410  Start looking for the object
1411 */
1412  for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
1413  for ( j = 0; j < NUMOBJECTS; j++ ) {
1414  if ( d->iblocks[i]->objects[j].tablenumber != tablenumber ) continue;
1415  s = arguments; t = d->iblocks[i]->objects[j].element;
1416  while ( *s == *t && *s ) { s++; t++; }
1417  if ( *t == 0 && *s == 0 ) return(1);
1418  }
1419  }
1420  return(0);
1421 }
1422 
1423 /*
1424  #] ExistsObject :
1425  #[ DeleteObject :
1426 
1427  Returns 1 if Object has been deleteted.
1428  We leave a hole. Actually the object is still there but has been
1429  inactivated. It can be reactivated by calling this routine again.
1430 */
1431 
1432 int DeleteObject(DBASE *d,MLONG tablenumber,char *arguments)
1433 {
1434  MLONG i, j;
1435  char *s, *t;
1436  if ( tablenumber > d->topnumber ) {
1437  MesPrint("Reference to non-existing table number in tablebase %s: %ld\n",
1438  d->name,tablenumber);
1439  return(0);
1440  }
1441 /*
1442  Start looking for the object
1443 */
1444  for ( i = 0; i < d->info.numberofindexblocks; i++ ) {
1445  for ( j = 0; j < NUMOBJECTS; j++ ) {
1446  if ( d->iblocks[i]->objects[j].tablenumber != tablenumber ) continue;
1447  s = arguments; t = d->iblocks[i]->objects[j].element;
1448  while ( *s == *t && *s ) { s++; t++; }
1449  if ( *t == 0 && *s == 0 ) {
1450  d->iblocks[i]->objects[j].tablenumber =
1451  -d->iblocks[i]->objects[j].tablenumber - 1;
1452  return(1);
1453  }
1454  }
1455  }
1456  return(0);
1457 }
1458 
1459 /*
1460  #] DeleteObject :
1461 */
1462 
Definition: minos.h:82
int size
Definition: structs.h:209
Definition: minos.h:94
UBYTE * argtail
Definition: structs.h:349
Definition: minos.h:120
Definition: structs.h:204