source: abuse/trunk/src/imlib/specs.cpp @ 540

Last change on this file since 540 was 540, checked in by Sam Hocevar, 11 years ago

tool: get rid of the specfile additions and implement a general purpose
SPEC file edition tool.

File size: 20.1 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 *  This software was released into the Public Domain. As with most public
7 *  domain software, no warranty is made or implied by Crack dot Com or
8 *  Jonathan Clark.
9 */
10
11#include "config.h"
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <stdint.h>
16#include <ctype.h>
17#include <fcntl.h>
18#include <math.h>
19#include <unistd.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22
23#include "common.h"
24
25#include "image.h"
26#include "palette.h"
27#include "specs.h"
28#include "dprint.h"
29
30char const *spec_types[] =
31{
32    "Invalid type", // 0
33    "Color table",  // 1
34    "Palette",      // 2
35    "Invalid Type", // 3
36    "Image",        // 4
37    "Fore Tile",
38    "Back Tile",
39    "Character",
40    "8 Morph",
41    "16 Morph",
42    "Grue objs",
43    "Extern WAV",
44    "DMX MUS",
45    "Patched morph",
46    "Normal file",
47    "Compress1 file",
48    "Vector Image",
49    "Light list",
50    "Grue fgmap",
51    "Grue bgmap",
52    "Data array",
53    "Character2",
54    "Particle",
55    "Extern lcache"
56};
57
58
59int total_files_open=0;
60char spec_main_file[100];
61
62static char *spec_prefix=NULL;
63static char *save_spec_prefix=NULL;
64
65static jFILE spec_main_jfile((FILE*)0);
66static int spec_main_fd = -1;
67static long spec_main_offset = -1;
68static spec_directory spec_main_sd;
69
70static int fast_load_fd = -1;
71static int fast_load_mode = 0;
72
73void set_filename_prefix(char const *prefix)
74{
75    if( spec_prefix )
76    {
77        free( spec_prefix );
78    }
79
80    if( prefix )
81    {
82        spec_prefix = strcpy( (char *)malloc( strlen( prefix ) + 2 ), prefix );
83        int len = strlen( prefix );
84        if( prefix[len - 1] != '\\' && prefix[len - 1] != '/')
85        {
86            spec_prefix[len] = '/';
87            spec_prefix[len + 1] = 0;
88        }
89    }
90    else
91    {
92        spec_prefix = NULL;
93    }
94}
95
96char *get_filename_prefix()
97{
98    return spec_prefix;
99}
100
101
102void set_save_filename_prefix(char const *save_prefix)
103{
104    if( save_spec_prefix )
105    {
106        free( save_spec_prefix );
107    }
108
109    if( save_prefix )
110    {
111        int len = strlen( save_prefix );
112        save_spec_prefix = (char *)malloc( len + 1 );
113        strcpy( save_spec_prefix, save_prefix );
114/* AK - Commented this out as it may cause problems
115        if( save_prefix[len - 1] != '\\' && save_prefix[len - 1] != '/' )
116        {
117            save_spec_prefix[len] = '/';
118            save_spec_prefix[len + 1] = '\0';
119        } */
120    }
121    else
122    {
123        save_spec_prefix = NULL;
124    }
125}
126
127char *get_save_filename_prefix()
128{
129  return save_spec_prefix;
130}
131
132int search_order=SPEC_SEARCH_OUTSIDE_INSIDE;
133
134static void (*no_space_handle_fun)()=NULL;
135
136void set_no_space_handler(void (*handle_fun)())
137{
138  no_space_handle_fun=handle_fun;
139}
140
141
142bFILE::bFILE()
143{
144  rbuf_size=8192;
145  rbuf=(unsigned char *)malloc(rbuf_size);
146  rbuf_start=rbuf_end=0;
147
148  wbuf_size=8192;
149  wbuf=(unsigned char *)malloc(wbuf_size);
150  wbuf_end=0;
151}
152
153bFILE::~bFILE()
154{
155  if (rbuf) free(rbuf);
156  flush_writes();
157  if (wbuf) free(wbuf);
158}
159
160int bFILE::flush_writes()
161{
162  if (wbuf_end!=0)
163  {
164    unsigned long ret=unbuffered_write(wbuf,wbuf_end);
165    if (ret!=wbuf_end && no_space_handle_fun)
166      no_space_handle_fun();
167
168    wbuf_end=0;
169    return ret;
170  }
171  return 0;
172}
173
174int bFILE::read(void *buf, size_t count)       // returns number of bytes read, calls unbuffer_read
175{
176  if (!allow_read_buffering())
177    return unbuffered_read(buf,count);
178
179  int total_read=0,error=0;
180  if (!count) return 0;
181  while (count && !error)
182  {
183    if (rbuf_start<rbuf_end)
184    {
185      unsigned int avail_size=rbuf_end-rbuf_start;
186      int copy_size=avail_size>count ? count : avail_size;
187      memcpy(buf,rbuf+rbuf_start,copy_size);
188      buf=(void *)(((unsigned char *)buf)+copy_size);
189      rbuf_start+=copy_size;
190      if (rbuf_start>=rbuf_end)
191      {
192                if (rbuf_end!=rbuf_size)  // buffer wasn't full before so there is no way we can complete read
193                  error=1;
194                rbuf_start=rbuf_end=0;
195      }
196      total_read+=copy_size;
197      count-=copy_size;
198    } else
199    {
200      rbuf_end=unbuffered_read(rbuf,rbuf_size);
201      if (rbuf_end==0) error=1;
202      rbuf_start=0;
203    }
204  }
205  return total_read;
206}
207
208
209int bFILE::write(void const *buf, size_t count)      // returns number of bytes written
210{
211  if (allow_write_buffering())
212  {
213    int total_written=0;
214    while (count)
215    {
216      int copy_size=wbuf_end+count<=wbuf_size ? count :  wbuf_size-wbuf_end;
217      memcpy(wbuf+wbuf_end,buf,copy_size);
218      wbuf_end+=copy_size;
219      count-=copy_size;
220      buf=(void *)(((char *)buf)+copy_size);
221      if (wbuf_end==wbuf_size)
222        if ((unsigned int)flush_writes()!=wbuf_size)
223      return total_written;
224
225      total_written+=copy_size;
226    }
227    return total_written;
228  } else
229  {
230    unsigned long ret=unbuffered_write(buf,count);
231    if (ret!=count && no_space_handle_fun)
232      no_space_handle_fun();
233  }
234  return 0;
235}
236
237int bFILE::seek(long offset, int whence) // whence=SEEK_SET, SEEK_CUR, SEEK_END, ret=0=success
238{
239//    rbuf_start=rbuf_end=0;
240//    unbuffered_seek(offset,SEEK_SET);
241
242  long realpos=unbuffered_tell();
243  long curpos=realpos-rbuf_end+rbuf_start;
244  if (whence==SEEK_CUR) offset+=curpos;
245  else if (whence==SEEK_END) offset=file_size()-offset;
246
247  if (offset<realpos-(long)rbuf_end || offset>=realpos)
248  {
249    rbuf_start=rbuf_end=0;
250    unbuffered_seek(offset,SEEK_SET);
251  } else
252    rbuf_start=rbuf_end-(realpos-offset);
253  return 1;
254}
255
256int bFILE::tell()
257{
258  return unbuffered_tell()-rbuf_end+rbuf_start+
259         wbuf_end;    // if this a write file, add on how much we've written
260}
261
262int bFILE::allow_read_buffering() { return 1; }
263int bFILE::allow_write_buffering() { return 1; }
264
265void set_spec_main_file(char const *filename, int Search_order)
266{
267  dprintf("Specs : main file set to %s\n",filename);
268  strcpy(spec_main_file,filename);
269  search_order=Search_order;
270
271#if (defined(__APPLE__) && !defined(__MACH__))
272  spec_main_jfile.open_external(filename,"rb",O_BINARY|O_RDONLY);
273#else
274  spec_main_jfile.open_external(filename,"rb",O_RDONLY);
275#endif
276  spec_main_fd = spec_main_jfile.get_fd();
277  if (spec_main_fd==-1)
278    return;
279  spec_main_sd.startup(&spec_main_jfile);
280}
281
282void fast_load_start_recording(char *filename)
283{
284    fast_load_fd = ::open(filename,O_CREAT|O_RDWR,S_IRWXU | S_IRWXG | S_IRWXO);
285    fast_load_mode = 1;
286}
287
288void fast_load_stop_recording()
289{
290    fast_load_mode = 0;
291}
292
293void fast_load_start_reloading(char *filename)
294{
295    fast_load_fd = ::open(filename,O_RDONLY);
296    fast_load_mode = 2;
297}
298
299void fast_load_stop_reloading()
300{
301    fast_load_mode = 0;
302}
303
304jFILE::jFILE(FILE *file_pointer)                       // assumes fp is at begining of file
305{
306  access=0;
307  fd=-1;
308  file_length=0;
309  start_offset=0;
310  flags=JFILE_CLONED;
311}
312
313void jFILE::open_external(char const *filename, char const *mode, int flags)
314{
315  int skip_size=0;
316  char tmp_name[200];
317  if (spec_prefix && filename[0] != '/')
318    sprintf(tmp_name,"%s%s",spec_prefix,filename);
319  else strcpy(tmp_name,filename);
320
321//  int old_mask=umask(S_IRWXU | S_IRWXG | S_IRWXO);
322  if (flags&O_WRONLY)
323  {
324    if ((flags&O_APPEND)==0)
325    {
326      skip_size=1;
327      //int errval = unlink(tmp_name);
328    }
329
330    flags-=O_WRONLY;
331    flags|=O_CREAT|O_RDWR;
332
333    fd=open(tmp_name,flags,S_IRWXU | S_IRWXG | S_IRWXO);
334  } else
335    fd=open(tmp_name,flags);
336
337//  umask(old_mask);
338  if (fd>=0 && !skip_size)
339  {
340    file_length=lseek(fd,0,SEEK_END);
341    if ((flags&O_APPEND)==0)
342      lseek(fd,0,SEEK_SET);
343    else
344        current_offset = file_length;
345    start_offset=0;
346  } else
347  {
348    file_length=0;
349    start_offset=0;
350  }
351}
352
353
354class null_file : public bFILE     // this file type will use virtual opens inside of a spe
355{
356  public :
357  virtual int open_failure() { return 1; }
358  virtual int unbuffered_read(void *buf, size_t count)   { return 0; }
359  virtual int unbuffered_write(void const *buf, size_t count)  { return 0; }
360  virtual int unbuffered_seek(long offset, int whence)   { return 0; }
361
362  virtual int unbuffered_tell() { return 0; }
363  virtual int file_size() { return 0; }
364  virtual ~null_file() { ; }
365} ;
366
367
368static bFILE *(*open_file_fun)(char const *,char const *)=NULL;
369int (*verify_file_fun)(char const *,char const *)=NULL;
370
371void set_file_opener(bFILE *(*open_fun)(char const *, char const *))
372{
373  open_file_fun=open_fun;
374}
375
376bFILE *open_file(char const *filename, char const *mode)
377{
378  if (!verify_file_fun || verify_file_fun(filename,mode))
379  {
380    if (open_file_fun)
381      return open_file_fun(filename,mode);
382    else return new jFILE(filename,mode);
383  } else return new null_file;
384}
385
386void jFILE::open_internal(char const *filename, char const *mode, int flags)
387{
388  int wr=0;
389  for (char const *s=mode; *s; s++)
390    if (toupper(*s)=='A' || toupper(*s)=='W')
391      wr=1;
392
393  if (wr)
394    fd=-1;                 // only allow extern file openings for writing
395  else
396  {
397       fd = spec_main_fd;
398    if (fd>=0)                    // if we were able to open the main file, see if it's in there
399    {
400      start_offset=0;
401      spec_entry *se=spec_main_sd.find(filename);
402      if (se)
403      {
404    start_offset=se->offset;
405    current_offset = 0;
406    file_length=se->size;
407    rbuf_start=rbuf_end=0;
408      } else
409      {
410    close(fd);
411    fd=-1;
412      }
413    }
414  }
415}
416
417jFILE::jFILE(char const *filename, char const *access_string)      // same as fopen parameters
418{
419 flags=access=0;
420 char const *s=access_string;
421  for (; *s; s++)
422    if (toupper(*s)=='R') access=O_RDONLY;
423
424  for (s=access_string; *s; s++)
425    if (toupper(*s)=='W')
426    {
427      if (access)
428        access=O_RDWR;
429      else access=O_WRONLY;
430    }
431
432  for (s=access_string; *s; s++)
433    if (toupper(*s)=='A')
434      access|=O_APPEND|O_WRONLY;
435
436  file_length=start_offset=-1;
437  current_offset = 0;
438
439  fd=-1;
440  if (search_order==SPEC_SEARCH_OUTSIDE_INSIDE)
441    open_external(filename,access_string,access);
442
443  if (fd<0)
444    open_internal(filename,access_string,access);
445
446  if (fd<0 && search_order==SPEC_SEARCH_INSIDE_OUTSIDE)
447    open_external(filename,access_string,access);
448
449  total_files_open++;
450}
451
452jFILE::~jFILE()
453{
454  flush_writes();
455  if (fd>=0 && !(flags&JFILE_CLONED))
456  {
457    total_files_open--;
458    if (fd != spec_main_fd)
459        close(fd);
460  }
461}
462
463int jFILE::unbuffered_tell()
464{
465//    int ret = ::lseek(fd,0,SEEK_CUR) - start_offset;
466//    if (ret != current_offset)
467//        fprintf(stderr,"Bad tell %d\n",current_offset);
468    return current_offset;
469}
470
471int jFILE::unbuffered_read(void *buf, size_t count)
472{
473    unsigned long len;
474
475    if (fd == spec_main_fd)
476    {
477        switch (fast_load_mode)
478        {
479        case 0:
480            if (current_offset+start_offset != spec_main_offset)
481                spec_main_offset = lseek(fd, start_offset+current_offset, SEEK_SET);
482
483            len = ::read(fd,(char*)buf,count);
484            break;
485        case 1:
486            if (current_offset+start_offset != spec_main_offset)
487                spec_main_offset = lseek(fd, start_offset+current_offset, SEEK_SET);
488
489            len = ::read(fd,(char*)buf,count);
490            ::write(fast_load_fd,(char*)&len,sizeof(len));
491            ::write(fast_load_fd,(char*)buf,len);
492            break;
493        case 2:
494            ::read(fast_load_fd,(char*)&len,sizeof(len));
495            len = ::read(fast_load_fd,(char*)buf,len);
496            break;
497        }
498
499        spec_main_offset += len;
500    }
501    else
502    {
503        switch (fast_load_mode)
504        {
505        case 0:
506          len = ::read(fd,(char*)buf,count);
507          break;
508        case 1:
509          len = ::read(fd,(char*)buf,count);
510            ::write(fast_load_fd,(char*)&len,sizeof(len));
511            ::write(fast_load_fd,(char*)buf,len);
512          break;
513        case 2:
514            ::read(fast_load_fd,(char*)&len,sizeof(len));
515            len = ::read(fast_load_fd,(char*)buf,len);
516            if (count != len)
517                printf("short read! %ld:%ld\n",current_offset,len);
518          break;
519      }
520    }
521    current_offset += len;
522    return len;
523}
524
525int jFILE::unbuffered_write(void const *buf, size_t count)
526{
527  long ret = ::write(fd,(char*)buf,count);
528    current_offset += ret;
529    return ret;
530}
531
532int jFILE::unbuffered_seek(long offset, int whence) // whence=SEEK_SET, SEEK_CUR, SEEK_END, ret=0=success
533{
534  long ret;
535
536  if (fast_load_mode == 2)
537  {
538    switch (whence)
539    {
540    case SEEK_SET :
541      current_offset = start_offset+offset;
542      break;
543    case SEEK_END :
544      current_offset = start_offset+file_length-offset;
545      break;
546    case SEEK_CUR :
547      current_offset += offset;
548      break;
549    default:
550      ret = -1;
551      break;
552    }
553    return current_offset;
554  }
555
556  switch (whence)
557  {
558    case SEEK_SET :
559    { ret = lseek(fd,start_offset+offset,SEEK_SET); } break;
560    case SEEK_END :
561    { ret = lseek(fd,start_offset+file_length-offset,SEEK_SET); } break;
562    case SEEK_CUR :
563    { ret = lseek(fd,offset,SEEK_CUR); } break;
564    default:
565        ret = -1;
566        break;
567  }
568  if (ret>=0)
569  {
570    current_offset = ret - start_offset;
571    if (spec_main_fd == fd)
572      spec_main_offset = ret;
573    return ret;
574  }
575  else
576    return -1;  // if a bad whence, then failure
577}
578
579
580uint8_t bFILE::read_uint8()
581{ uint8_t x;
582  read(&x,1);
583  return x;
584}
585
586uint16_t bFILE::read_uint16()
587{
588  uint16_t x;
589  read(&x,2);
590  return lstl(x);
591}
592
593
594uint32_t bFILE::read_uint32()
595{
596  uint32_t x;
597  read(&x,4);
598  return lltl(x);
599}
600
601void bFILE::write_uint8(uint8_t x)
602{
603  write(&x,1);
604}
605
606void bFILE::write_uint16(uint16_t x)
607{
608  x=lstl(x);
609  write(&x,2);
610}
611
612
613void bFILE::write_uint32(uint32_t x)
614{
615  x=lltl(x);
616  write(&x,4);
617}
618
619void bFILE::write_double(double x)
620{
621  double a;
622  write_uint32((long)(modf(x,&a)*(double)(1<<31)));
623  write_uint32((long)a);
624}
625
626double bFILE::read_double()
627{
628  long a,b;
629  a=read_uint32();
630  b=read_uint32();
631  return (double)b+a/(double)(1<<31);
632}
633
634spec_directory::~spec_directory()
635{
636
637  if (total)
638  {
639    free(data);
640    free(entries);
641  }
642}
643
644void spec_entry::print()
645{
646  printf("%15s%25s%8ld%8ld\n",spec_types[type],name,size,offset);
647}
648
649void spec_directory::calc_offsets()
650{
651  spec_entry **e;
652  int i;
653  long o=SPEC_SIG_SIZE+2;
654  if (total)
655  {
656    for (i=0,e=entries; i<total; i++,e++)          // calculate the size of directory info
657    {
658      o+=1+1+strlen((*e)->name)+1 +1 +8;
659    }
660
661    for (i=0,e=entries; i<total; i++,e++)          // calculate offset for each entry
662    {
663      (*e)->offset=o;
664      o+=(*e)->size;
665    }
666  }
667}
668
669spec_entry *spec_directory::find(char const *name, int type)
670{
671  int i;
672  spec_entry **e;
673  for (i=0,e=entries; i<total; i++,e++)
674    if (!strcmp((*e)->name,name) && (*e)->type==type)
675      return (*e);
676  return NULL;
677}
678
679spec_entry *spec_directory::find(char const *name)
680{
681  int i;
682  spec_entry **e;
683  for (i=0,e=entries; i<total; i++,e++)
684    if (!strcmp((*e)->name,name))
685      return (*e);
686  return NULL;
687}
688
689long spec_directory::find_number(char const *name)
690{
691  int i;
692  spec_entry **e;
693  for (i=0,e=entries; i<total; i++,e++)
694    if (!strcmp((*e)->name,name))
695      return i;
696  return -1;
697}
698
699spec_entry *spec_directory::find(int type)
700{
701  int i;
702  spec_entry **e;
703  for (i=0,e=entries; i<total; i++,e++)
704    if ((*e)->type==type)
705      return (*e);
706  return NULL;
707}
708
709long spec_directory::type_total(int type)
710{
711  int i,x=0;
712  spec_entry **e;
713  for (i=0,e=entries; i<total; i++,e++)
714    if ((*e)->type==type) x++;
715  return x;
716}
717
718long spec_directory::find_number(int type)
719{
720  int i;
721  spec_entry **e;
722  for (i=0,e=entries; i<total; i++,e++)
723    if ((*e)->type==type)
724      return i;
725  return -1;
726}
727
728void spec_directory::print()
729{
730  spec_entry **se;
731  int i;
732  printf("[   Entry type   ][   Entry name   ][  Size  ][ Offset ]\n");
733  for (i=0,se=entries; i<total; i++,se++)
734    (*se)->print();
735}
736
737
738void spec_directory::startup(bFILE *fp)
739{
740  char buf[256];
741  memset(buf,0,256);
742  fp->read(buf,8);
743  buf[9]=0;
744  size=0;
745  if (!strcmp(buf,SPEC_SIGNATURE))
746  {
747    total=fp->read_uint16();
748    entries=(spec_entry **)malloc(sizeof(spec_entry *)*total);
749    long start=fp->tell();
750
751    int i;
752    for (i=0; i<total; i++)
753    {
754      fp->read(buf,2);
755      long entry_size=sizeof(spec_entry)+(unsigned char)buf[1];
756      entry_size=(entry_size+3)&(~3);
757      fp->read(buf,(unsigned char)buf[1]);
758      fp->read(buf,9);
759
760      size+=entry_size;
761    }
762    data=malloc(size);
763    char *dp=(char *)data;
764    fp->seek(start,SEEK_SET);
765    for (i=0; i<total; i++)
766    {
767      spec_entry *se=(spec_entry *)dp;
768      entries[i]=se;
769
770      unsigned char len,flags,type;
771      fp->read(&type,1);
772      fp->read(&len,1);
773      se->type=type;
774      se->name=dp+sizeof(spec_entry);
775      fp->read(se->name,len);
776      fp->read(&flags,1);
777
778      se->size=fp->read_uint32();
779      se->offset=fp->read_uint32();
780      dp+=((sizeof(spec_entry)+len)+3)&(~3);
781    }
782  }
783  else
784  {
785    total=0;
786    data=NULL;
787    entries=NULL;
788  }
789}
790
791
792spec_directory::spec_directory(bFILE *fp)
793{ startup(fp); }
794
795spec_directory::spec_directory(FILE *fp)
796{
797  jFILE jfp(fp);
798  startup(&jfp);
799}
800
801spec_directory::spec_directory()
802{
803  size=0;
804  total=0;
805  data=NULL;
806  entries=NULL;
807}
808
809/*
810spec_directory::spec_directory(char *filename)
811{
812  jFILE *fp;
813  if (filename)
814  {
815    fp=new jFILE(filename,"rb");
816    if (!fp->open_failure())
817      startup(fp);
818    else
819    {
820      total=0;
821      entries=NULL;
822    }
823    delete fp;
824  } else printf("NULL filename to spec_directory::spec_directory\n");
825}*/
826
827int write_string(bFILE *fp, char const *st)
828{
829  unsigned char length=strlen(st)+1;
830  if (fp->write(&length,1)!=1) return 0;
831  if (fp->write(st,length)!=length) return 0;
832  return 1;
833}
834
835long spec_directory::data_start_offset()
836{
837    /* FIXME: no need for a for loop here! */
838    long i;
839    for(i = 0; i < total; i++)
840        return entries[i]->offset;
841
842    // If no entries, then no data, but return where it would start anyway
843    return SPEC_SIG_SIZE + 2;
844}
845
846long spec_directory::data_end_offset()
847{
848    /* FIXME: no need for a for loop here! */
849  spec_entry **e;
850  long i;
851  for (i=total-1,e=entries; i>=0; i--,e++)
852    return (*e)->offset+(*e)->size;
853
854  return SPEC_SIG_SIZE+2;
855}
856
857int spec_directory::write(bFILE *fp)
858{
859
860  char sig[SPEC_SIG_SIZE];
861  unsigned char flags=0;
862  unsigned long offset,data_size;
863  spec_entry **e;
864  strcpy(sig,SPEC_SIGNATURE);
865
866  if (fp->write(sig,sizeof(sig))!=sizeof(sig))    return 0;
867  fp->write_uint16(total);
868
869
870  int i;
871  for (i=0,e=entries; i<total; i++,e++)
872  {
873    if (fp->write(&(*e)->type,1)!=1)                 return 0;
874    if (!write_string(fp,(*e)->name))                return 0;
875    flags=0;
876    if (fp->write(&flags,1)!=1)                     return 0;
877
878    data_size=lltl((*e)->size);
879    if (fp->write((char *)&data_size,4)!=4)              return 0;
880    offset=lltl((*e)->offset);
881    if (fp->write((char *)&offset,4)!=4)                  return 0;
882
883  }
884  return 1;
885}
886
887jFILE *spec_directory::write(char const *filename)
888{
889  jFILE *fp;
890  fp=new jFILE(filename,"wb");
891  if (fp->open_failure()) { delete fp; return NULL; }
892  if (!write(fp))
893  {
894    delete fp;
895    return NULL;
896  } else return fp;
897
898}
899
900uint16_t read_uint16(FILE *fp)
901{
902  uint16_t x;
903  fread(&x,1,2,fp);
904  return lstl(x);
905}
906
907uint32_t read_uint32(FILE *fp)
908{
909  uint32_t x;
910  fread(&x,1,4,fp);
911  return lltl(x);
912}
913void write_uint16(FILE *fp, uint16_t x)
914{
915  x=lstl(x);
916  fwrite(&x,1,2,fp);
917}
918
919void write_uint32(FILE *fp, uint32_t x)
920{
921  x=lltl(x);
922  fwrite(&x,1,4,fp);
923}
924
925uint8_t read_uint8(FILE *fp) { return fgetc(fp)&0xff; }
926void write_uint8(FILE *fp, uint8_t x) { fputc((unsigned char)x,fp); }
927
928void spec_directory::remove(spec_entry *e)
929{
930  int i;
931  for (i=0; i<total && entries[i]!=e; i++);            // find the entry in the array first
932
933  if (entries[i]==e)                                 // make sre it was found
934  {
935    delete e;
936    total--;
937    for (; i<total; i++)                               // compact the pointer array
938      entries[i]=entries[i+1];
939    entries=(spec_entry **)realloc(entries,sizeof(spec_entry *)*total);
940  }
941  else
942    printf("Spec_directory::remove bad entry pointer\n");
943}
944
945
946
947void spec_directory::add_by_hand(spec_entry *e)
948{
949  total++;
950  entries=(spec_entry **)realloc(entries,sizeof(spec_entry *)*total);
951  entries[total-1]=e;
952}
953
954void spec_directory::delete_entries()   // if the directory was created by hand instead of by file
955{
956  int i;
957  for (i=0; i<total; i++)
958    delete entries[i];
959
960  if (total)
961    free(entries);
962}
963
964void note_open_fd(int fd, char const *str)
965{
966    total_files_open++;
967}
968
969void note_close_fd(int fd)
970{
971    total_files_open--;
972}
973
974void list_open_fds()
975{
976    printf("Total open file descriptors: %d\n", total_files_open);
977}
978
Note: See TracBrowser for help on using the repository browser.