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"
45int withoutflush = 0;
46
47/*
48 #] Includes :
49 #[ Variables :
50*/
51
52static INDEXBLOCK scratchblock;
53static 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
66int 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
83int 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
101char *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
120void 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
171void 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
197void 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
225FILE *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
287int 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);
333thisiswrong:
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
400int 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
421int 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
444int 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
507int 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
524int 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
547DBASE *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
591DBASE *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) ) {
648getout:
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
725void 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
757int 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 }
783gotall:;
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
806DBASE *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
840MLONG 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
923MLONG 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
955int 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
1051int 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;
1065dowrite:
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
1138MLONG 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
1152MLONG 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
1180int 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
1271char *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
1308foundelement:;
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
1352char *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
1404int 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
1436int 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*/
int size
Definition structs.h:209
UBYTE * argtail
Definition structs.h:361
Definition minos.h:120