• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*---------------------------------------------------------------------------*
2  *  pstream.c  *
3  *                                                                           *
4  *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
5  *                                                                           *
6  *  Licensed under the Apache License, Version 2.0 (the 'License');          *
7  *  you may not use this file except in compliance with the License.         *
8  *                                                                           *
9  *  You may obtain a copy of the License at                                  *
10  *      http://www.apache.org/licenses/LICENSE-2.0                           *
11  *                                                                           *
12  *  Unless required by applicable law or agreed to in writing, software      *
13  *  distributed under the License is distributed on an 'AS IS' BASIS,        *
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15  *  See the License for the specific language governing permissions and      *
16  *  limitations under the License.                                           *
17  *                                                                           *
18  *---------------------------------------------------------------------------*/
19 
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 
24 #include <string.h>
25 #include "passert.h"
26 #include "pstdio.h"
27 #include "pmemory.h"
28 #include "plog.h"
29 
30 #ifdef __cplusplus
31 extern "C"
32 {
33 #endif
34 
35 #ifdef PFILE_VIRTUAL_SUPPORT
36 
37 #define FILETEXTMODE    0x00
38 #define FILEBINARYMODE   0x01
39 #define FILEREADMODE    0x00
40 #define FILEWRITEMODE    0x02
41 
42   /* Open a existed writable file (i.e., the file is not closed yet).
43      At some cases user knows the filename only but does not know the file handle (1),
44      the user could call fopen to open this file again with another file handle (2).
45      He/She could get all the information before the last fflush was called via file handle (1).
46    */
47 #define FILEREOPENMODE 0x08
48 
49 #define ISWRITEMODE(mode)  (((mode)&FILEWRITEMODE)  == FILEWRITEMODE)
50 
51 #define ISBINARYMODE(mode) (((mode)&FILEBINARYMODE) == FILEBINARYMODE)
52 #define ISREOPENMODE(mode) (((mode)&FILEREOPENMODE) == FILEREOPENMODE)
53 
54   /*
55     use a double link list to store the data of the writable file.
56     Each entry has 4k space (FILEBUFFERSIZE).
57   */
58 #define FILEBUFFERSIZE 4096     /* 4k for each file buffer entry */
59 
60   typedef struct FileBufferFrame
61   {
62     unsigned char          *buffer;       /* do not use pointer here and set it the first */
63     size_t                  size;
64     size_t                index;                        /* nth buffer, from 0, 1, ... */
65     struct FileBufferFrame  *prev;
66     struct FileBufferFrame  *next;
67     BOOL                    bMalloc;        /* flag, if the buffer malloced here ? */
68   }
69   FileBufferFrame;
70 
71   FileRecord pWritableFileRecTable[] =
72     {
73       {"", 0, 0, 0, 3},
74       {"", 0, 0, 0, 3},
75       {"", 0, 0, 0, 3},
76       {"", 0, 0, 0, 3},
77       {"", 0, 0, 0, 3},
78       {"", 0, 0, 0, 3},
79       {"", 0, 0, 0, 3}
80     };
81   const nWritableFiles = sizeof(pWritableFileRecTable) / sizeof(pWritableFileRecTable[0]);
82 
83 #ifdef WIN32
84   extern const FileRecord pFileRecTable[];
85   extern const unsigned char pFileStart0[];
86 #endif
87 
88   const FileRecord *pReadOnlyFileRecTable = NULL;
89   const unsigned char *g_pFirstFile = NULL;
90 
SetFileTable(VirtualFileTable * table)91   void SetFileTable(VirtualFileTable *table)
92   {
93 #ifdef WIN32
94     pReadOnlyFileRecTable = pFileRecTable;
95     g_pFirstFile = pFileStart0;
96 #else
97     if (table)
98     {
99       pReadOnlyFileRecTable = table->pFileTable;
100       g_pFirstFile = table->pFirstFile;
101     }
102 #endif
103   }
104 
105   /*
106     size: size of buffer.
107     buffer: is NULL, allocate here and set bMalloc as TRUE; otherwise use the external buffer
108   */
CreateFileBufferFrame(size_t size,unsigned char * buffer)109   FileBufferFrame* CreateFileBufferFrame(size_t size, unsigned char *buffer)
110   {
111     FileBufferFrame *fb = NULL;
112 
113     /* create FileBufferFrame */
114     fb = (FileBufferFrame *)MALLOC(sizeof(FileBufferFrame), "FileBufferFrame");
115     if (fb)
116     {
117       fb->next = NULL;
118       fb->prev = NULL;
119       fb->index = 0;
120       fb->size = size;
121       fb->bMalloc = FALSE;
122 
123       if (buffer)
124         fb->buffer = buffer;
125       else
126       {
127         /* create one buffer frame */
128         if ((fb->buffer = (unsigned char *)MALLOC(size, "FileBufferFrame Buffer")) == NULL)
129         {
130           FREE(fb);
131           return NULL;
132         }
133         fb->bMalloc = TRUE;
134       }
135     }
136     return fb;
137   }
138 
139   /* free FileBufferFrames
140      header should be the header of the FileBufferFrame link list
141    */
DeleteFileBuffers(FileBufferFrame * header)142   void DeleteFileBuffers(FileBufferFrame *header)
143   {
144     FileBufferFrame *next, *curr;
145 
146     passert(header && header->prev == NULL);    /* delete from the beginning */
147 
148     curr = header;
149     do
150     {
151       next = curr->next;
152       if (curr->bMalloc)
153         FREE(curr->buffer);
154       FREE(curr);
155       curr = next;
156     }
157     while (next != NULL);
158   }
159 
PortFileInit(void)160   void PortFileInit(void)
161   {
162     /* No gPortStdin, gPortStdout, and gPortStderr to initialize. */
163 #ifdef WIN32
164     pReadOnlyFileRecTable = pFileRecTable;
165     g_pFirstFile = pFileStart0;
166 #endif
167   }
168 
169   /* Assume that all files have at least one byte in them, that is length is > 0. */
PortFopen(const char * filename,const char * mode)170   PORT_FILE PortFopen(const char *filename, const char *mode)
171   {
172     char *pfn;
173     const unsigned char *start;
174     int size;
175     int text_mode;
176     int access_mode;
177     int m = 0;
178     PORT_FILE PortFile;
179     FileBufferFrame *curFrame;
180     size_t end;
181 
182     passert(filename);
183     passert(mode);
184 
185     if (pReadOnlyFileRecTable == NULL)
186     {
187       passert("File Table is not initialized!" == NULL);
188       return NULL;
189     }
190 
191     /* support read and write. */
192     if (mode[0] == 'r' || mode[0] == 'w' || mode[0] == 'R') /* w means w+, attaching text */
193     {
194       char fname[80];
195       FileRecord *pCurRec;
196 
197       access_mode  = (mode[0] == 'r') ? FILEREADMODE   : FILEWRITEMODE;
198 
199       /* access mode: b/t */
200       if (mode[1] == '+')
201         text_mode = (mode[2] == 'b') ? FILEBINARYMODE : FILETEXTMODE;
202       else
203         text_mode = (mode[1] == 'b') ? FILEBINARYMODE : FILETEXTMODE;
204 
205       /* Remove the directory path from the filename. */
206       if ((pfn = strrchr(filename, '/')) != NULL || (pfn = strrchr(filename, '\\')) != NULL)
207         strcpy(fname, pfn + 1);
208       else
209         strcpy(fname, filename);
210 
211 
212       /* Locate the start of the file, by looking through the file record table. */
213       if (access_mode == FILEREADMODE)
214       {
215         pCurRec = (FileRecord *)pReadOnlyFileRecTable;
216         start = g_pFirstFile;
217       }
218       else
219       {
220         pCurRec = (FileRecord *)pWritableFileRecTable;
221       }
222 
223       while (pCurRec->size > 0 && strcmp(pCurRec->name, fname) != 0)
224       {
225         /* have to count the read-only file address in order to be best portable */
226         start += pCurRec->size;
227         pCurRec++;
228 #ifndef NDEBUG
229         /* just for our internal test for read-only files.
230         if (pCurRec->start != NULL)
231         passert(start == pCurRec->start);
232         */
233 #endif
234       }
235 
236       m = access_mode | text_mode;
237       /* Do not support reopen the writable file now. */
238       if (access_mode == FILEREADMODE)
239       {
240         if (pCurRec->size == 0)
241         {
242           return NULL;
243         }
244 
245         /* Found the file, record it's starting offset and length. */
246         end = pCurRec->end;
247         size = pCurRec->size;
248       }
249       /* writable file, open it the first time; could be text or binary */
250       else if (ISWRITEMODE(access_mode))
251       {
252         /* set the name and mode */
253         strcpy(pCurRec->name, fname);
254         pCurRec->mode = m;
255 
256         start = pCurRec->start;
257         passert(start == NULL);
258         end = size = FILEBUFFERSIZE;
259       }
260       else
261       {
262         /* File doesn't exist. */
263         return NULL;
264       }
265       pfn = pCurRec->name;
266     }
267     else
268     {
269       /* Unknown mode */
270       return NULL;
271     }
272 
273     /* Open file */
274     /* Create new file handle */
275     PortFile = (PORT_FILE)MALLOC(sizeof(PORT_FILE_HANDLE), "PortFile");
276     if (PortFile == NULL)
277     {
278       return NULL;
279     }
280 
281     /* this mode is not tested yet */
282     if (ISREOPENMODE(m))
283     {
284       PortFile->startFrame = (FileBufferFrame *)start;
285     }
286     else
287     {
288       PortFile->startFrame = CreateFileBufferFrame(size, (unsigned char *)start);
289       if (ISWRITEMODE(m))
290       {
291         start = (const unsigned char *)PortFile->startFrame;
292       }
293     }
294 
295     if (PortFile->startFrame == NULL)
296     {
297       FREE(PortFile);
298       return NULL;
299     }
300 
301     PortFile->endFrame = PortFile->curFrame = PortFile->startFrame;
302 
303     /* Mark that this file handle is for flash memory */
304     PortFile->filename = pfn;
305     PortFile->curPos = PortFile->curFrame->buffer;
306     PortFile->endPos = PortFile->curPos + end;
307 
308     /* set the PortFile->endPos */
309     curFrame = PortFile->curFrame;
310     while (end > 0)
311     {
312       if (end > curFrame->size)
313       {
314         curFrame = curFrame->next;
315         passert(end > curFrame->size);
316         end -= curFrame->size;
317         passert(curFrame);
318       }
319       else
320       {
321         /* only reopen the writable file comes here */
322         PortFile->endPos = curFrame->buffer + end;
323         break;
324       }
325     }
326 
327     PortFile->eof = 0; /* File must have at least one byte in it. */
328     PortFile->size =  size;
329     PortFile->mode =  m;
330 
331     return PortFile;
332   }
333 
PortFclose(PORT_FILE PortFile)334   int PortFclose(PORT_FILE PortFile)
335   {
336     passert(PortFile);
337 
338     /* for reopen mode, do not delete the FileBufferFrame. Delete it by who created it */
339     if (ISWRITEMODE(PortFile->mode) && !ISREOPENMODE(PortFile->mode))  /* writable file */
340     {
341       int i = 0;
342       FileRecord *pCurRec = (FileRecord *)pWritableFileRecTable;
343 
344       /* find the file record in memory */
345       for (i = 0; i < nWritableFiles; i++)
346       {
347         if (PortFile->size > 0 &&
348             PortFile->filename[0] != '\0' &&
349             strcmp(pCurRec->name, PortFile->filename) == 0
350            )
351         {
352           /* The parameter SREC.Recognizer.osi_log_level in par file control the output
353             # BIT 0 -> BASIC logging
354             # BIT 1 -> AUDIO waveform logging
355             # BIT 2 -> ADD WORD logging
356             # e.g. value is 3 = BASIC+AUDIO logging, no ADDWORD
357             SREC.Recognizer.osi_log_level = 7;
358 
359             Do not control here
360           */
361           /*
362           SaveFileToDisk(PortFile);
363           */
364 
365           pCurRec->name[0] = '\0';
366           pCurRec->start = NULL;
367           pCurRec->end = 0;
368           pCurRec->size = 0;
369 
370           break;
371         }
372         pCurRec++;
373       }
374     }
375 
376     DeleteFileBuffers(PortFile->startFrame);
377     FREE(PortFile);
378     return 0;
379   }
380 
381   /*
382    * Returns the number of items read
383    */
PortFread(void * buffer,size_t size,size_t count,PORT_FILE PortFile)384   size_t PortFread(void *buffer, size_t size, size_t count, PORT_FILE PortFile)
385   {
386     unsigned char *bufferPtr = (unsigned char *)buffer;
387     int cbRemain = size * count;
388     int cbAvail, minSize;
389     FileBufferFrame *curFrame = PortFile->curFrame;
390 
391     passert(buffer);
392     passert(PortFile);
393 
394     if (PortFile->eof == 1)
395     {
396       return 0;
397     }
398 
399     while (cbRemain > 0)
400     {
401       if (PortFile->endPos == PortFile->curPos)  /* end of file */
402         break;
403 
404       if (PortFile->curPos == curFrame->buffer + curFrame->size) /* end of this frame */
405       {
406         /* go to next frame */
407         curFrame = PortFile->curFrame = curFrame->next;
408         PortFile->curPos = curFrame->buffer;
409       }
410 
411       if (curFrame == PortFile->endFrame)  /* last frame */
412         cbAvail = PortFile->endPos - PortFile->curPos;
413       else
414         cbAvail = curFrame->size - (PortFile->curPos - curFrame->buffer);
415 
416       minSize = cbRemain < cbAvail ? cbRemain : cbAvail;
417       passert(minSize >= 0);
418 
419       cbRemain -= minSize;
420       while (minSize-- > 0)
421         *bufferPtr++ = *PortFile->curPos++;
422     }
423 
424     if (PortFile->curPos == PortFile->endPos)
425     {
426       PortFile->eof = 1;
427     }
428     /*
429     #ifdef __BIG_ENDIAN
430      if (!bNativeEnding)
431      {
432       swap_byte_order((char *)buffer, count, size);
433      }
434     #endif
435     */
436     return count - cbRemain / size;
437   }
438 
439   /*
440    * Returns the number of items written
441    */
PortFwrite(const void * data,size_t size,size_t count,PORT_FILE PortFile)442   size_t PortFwrite(const void *data, size_t size, size_t count, PORT_FILE PortFile)
443   {
444     int cbWrite = size * count;
445     int cbAvail, minSize;
446     unsigned char *buffer = (unsigned char *)data;
447     FileBufferFrame *curFrame;
448 
449     if (PortFile == NULL)
450       return 0;
451 
452     curFrame = PortFile->curFrame;
453 
454     /* write data until the end of the internal buffer */
455     if (PortFile->eof == 1)
456     {
457       /* TODO: should return 0, but it will cause infinite loop */
458       return 0;
459     }
460 
461     /* why sub 1 ? */
462     while (cbWrite > 0)
463     {
464       if (PortFile->curPos == curFrame->buffer + curFrame->size) /* end of this frame */
465       {
466         if (curFrame->next == NULL)
467         {
468           /* assign a new space */
469           FileBufferFrame *nextFrame = CreateFileBufferFrame(FILEBUFFERSIZE, NULL);
470           if (nextFrame)
471           {
472             curFrame->next = nextFrame;
473             nextFrame->prev = curFrame;
474             nextFrame->index = curFrame->index + 1;
475 
476             curFrame = PortFile->curFrame = nextFrame;
477             PortFile->endFrame = nextFrame;
478             PortFile->curPos = PortFile->endPos = nextFrame->buffer;
479 
480             PortFile->size += FILEBUFFERSIZE;
481           }
482           else
483           {
484             return count -cbWrite / size;
485           }
486         }
487         else
488           curFrame = curFrame->next;
489       }
490 
491       /* available space in current frame */
492       cbAvail = curFrame->size - (PortFile->curPos - curFrame->buffer);
493       minSize = cbWrite < cbAvail ? cbWrite : cbAvail;
494 
495       memcpy((char *)PortFile->curPos, buffer, minSize);
496       buffer += minSize;
497       PortFile->curPos += minSize;
498       /* in case the write is not adding to the end */
499       if (curFrame == PortFile->endFrame && PortFile->endPos < PortFile->curPos)
500         PortFile->endPos = PortFile->curPos;
501       cbWrite -= minSize;
502     }
503 
504     return count;
505   }
506 
507   /*
508    * Returns 0 on success, non-zero on failure
509    */
PortFseek(PORT_FILE PortFile,long offset,int origin)510   int PortFseek(PORT_FILE PortFile, long offset, int origin)
511   {
512     int retval = 0;
513     int cbAvail, minSize;
514     FileBufferFrame *curFrame;
515 
516     passert(PortFile);
517 
518     /* Clear eof flag */
519     PortFile->eof = 0;
520 
521     switch (origin)
522     {
523       case SEEK_CUR:
524         break;
525       case SEEK_END:
526         PortFile->curFrame = PortFile->endFrame;
527         PortFile->curPos = PortFile->endPos;
528         break;
529       case SEEK_SET:
530         PortFile->curFrame = PortFile->startFrame;
531         PortFile->curPos = PortFile->startFrame->buffer;
532         break;
533       default:
534         retval = 0; /* Error, unknown origin type */
535         break;
536     }
537 
538     curFrame = PortFile->curFrame;
539 
540     while (offset != 0)
541     {
542       if (offset > 0)
543       {
544         if (PortFile->endPos <= PortFile->curPos)  /* end of file */
545           break;
546 
547         if (PortFile->curPos == curFrame->buffer + curFrame->size) /* end of this frame */
548         {
549           /* go to next frame */
550           curFrame = curFrame->next;
551           if (curFrame == NULL)
552             break;
553           PortFile->curFrame = curFrame->next;
554           PortFile->curPos = curFrame->buffer;
555         }
556         if (curFrame == PortFile->endFrame)  /* last frame */
557           cbAvail = PortFile->endPos - PortFile->curPos;
558         else
559           cbAvail = curFrame->size - (PortFile->curPos - curFrame->buffer);
560 
561         minSize = offset < cbAvail ? offset : cbAvail;
562 
563         PortFile->curPos += minSize;
564         offset -= minSize;
565       }
566       else
567       {
568         if (PortFile->startFrame->buffer == PortFile->curPos)  /* start of file */
569           break;
570 
571         if (PortFile->curPos <= curFrame->buffer) /* start of this frame */
572         {
573           /* go to next frame */
574           curFrame = curFrame->next;
575           if (curFrame == NULL)
576             break;
577           PortFile->curFrame = curFrame;
578           PortFile->curPos = curFrame->buffer + curFrame->size;
579         }
580         cbAvail = PortFile->curPos - curFrame->buffer;
581 
582         minSize = -offset < cbAvail ? -offset : cbAvail;
583 
584         PortFile->curPos -= minSize;
585         offset += minSize;
586       }
587     }
588     return retval;
589   }
590 
591   /*
592    * Returns current file position
593    */
PortFtell(PORT_FILE PortFile)594   long PortFtell(PORT_FILE PortFile)
595   {
596     int size;
597     FileBufferFrame *curFrame = PortFile->curFrame;
598 
599     passert(PortFile);
600 
601     /* current Frame size */
602     size = PortFile->curPos - curFrame->buffer;
603 
604     /* previous frame size */
605     while (curFrame = curFrame->prev)
606       size += curFrame->size;
607 
608     return size;
609   }
610 
PortVfprintf(PORT_FILE PortFile,const char * format,va_list argptr)611   int PortVfprintf(PORT_FILE PortFile, const char *format, va_list argptr)
612   {
613     char message[2*2048] = "";
614 
615     /* Print formatted message to buffer */
616     vsprintf(message, format, argptr);
617 
618     if (PortFile == NULL)
619     {
620       /* TODO: HECK to screen */
621 #ifndef NDEBUG
622       printf(message);
623 #endif
624       return 0;
625     }
626 
627     passert(strlen(message) < 2*2048);
628     /* TO DO, seems at case fprintf(pf, "whatever"), message is empty! */
629     if (strlen(message) == 0)
630       return 0;
631     else
632       return PortFwrite(message, sizeof(char), strlen(message), PortFile);
633   }
634 
635   /*
636    * Returns current file position
637    */
PortFprintf(PORT_FILE PortFile,const char * format,...)638   int PortFprintf(PORT_FILE PortFile, const char* format, ...)
639   {
640     va_list log_va_list;
641     int ret = 0;
642 
643     /* Start variable argument list */
644     va_start(log_va_list, format);
645 
646     /* Print formatted message to buffer */
647     ret = PortVfprintf(PortFile, format, log_va_list);
648 
649     /* End variable argument list */
650     va_end(log_va_list);
651 
652     return ret;
653   }
654 
655   /*
656    * Returns string or NULL if error
657    */
PortFgets(char * string,int n,PORT_FILE PortFile)658   char *PortFgets(char *string, int n, PORT_FILE PortFile)
659   {
660     int cbToRead = n - 1;
661     BOOL done = FALSE;
662     char *retString = NULL;
663     int i;
664 
665     passert(string);
666     passert(n);
667     passert(PortFile);
668 
669 
670     if (PortFile->eof == 1)
671     {
672       return NULL;
673     }
674 
675 
676     /* Search for \n only! */
677     for (i = 0; i < cbToRead && !done; i++)
678     {
679       if (PortFile->curPos >= PortFile->endPos)
680       {
681         PortFile->eof = 1;
682         done = TRUE;
683         break;
684       }
685       else if (*PortFile->curPos == '\n')
686       {
687         if (retString == NULL)
688         {
689           retString = string;
690         }
691         retString[i] = '\n';
692         PortFile->curPos++;
693         done = TRUE;
694       }
695       else
696       {
697         if (retString == NULL)
698         {
699           retString = string;
700         }
701         retString[i] = *PortFile->curPos++;
702       }
703     }
704     if (retString != NULL)
705     {
706       retString[i] = '\0';
707     }
708     return retString;
709   }
710 
711   /*
712    * Returns string or NULL if error
713    */
PortFflush(PORT_FILE PortFile)714   int PortFflush(PORT_FILE PortFile)
715   {
716     if (PortFile == NULL)
717     {
718       return -1;
719     }
720 
721 
722     /* call fflush before reopen a writable file */
723     if (ISWRITEMODE(PortFile->mode))  /* writable file */
724     {
725       FileRecord *pCurRec = (FileRecord *)pWritableFileRecTable;
726 
727       /* find the file record in memory */
728       do
729       {
730         if (strcmp(pCurRec->name, PortFile->filename) == 0)
731         {
732           /* assgin it as startFrame, so others could get information when reopen it */
733           pCurRec->start = (unsigned char *)PortFile->startFrame;
734           pCurRec->end = PortFile->size - PortFile->endFrame->size +
735                          (PortFile->endPos - PortFile->endFrame->buffer);
736           pCurRec->size = PortFile->size;
737           pCurRec->mode = PortFile->mode;
738 
739           break;
740         }
741         pCurRec++;
742       }
743       while (pCurRec->size > 0);
744     }
745     return 0;
746   }
747 
748 
PortFeof(PORT_FILE PortFile)749   int PortFeof(PORT_FILE PortFile)
750   {
751     passert(PortFile);
752 
753     return PortFile->eof;
754   }
755 
756   /*
757    * Returns character or EOF
758    */
PortFgetc(PORT_FILE PortFile)759   int PortFgetc(PORT_FILE PortFile)
760   {
761     int c;
762 
763     passert(PortFile);
764 
765     if (PortFile->eof == 1)
766     {
767       return EOF;
768     }
769     else
770     {
771       c = (int) * PortFile->curPos++;
772 
773       if (PortFile->curPos >= PortFile->endPos)
774       {
775         PortFile->eof = 1;
776       }
777     }
778     return c;
779   }
780 
781   /*
782    * Returns 0 if no error
783    */
PortFerror(PORT_FILE PortFile)784   int PortFerror(PORT_FILE PortFile)
785   {
786     passert(PortFile);
787 
788     return 0;
789   }
790 
PortClearerr(PORT_FILE PortFile)791   void PortClearerr(PORT_FILE PortFile)
792   {
793     PortFile->eof = 0;
794   }
795 
796   /*
797    * Returns current file position
798    */
PortFscanf(PORT_FILE PortFile,const char * format,...)799   int PortFscanf(PORT_FILE PortFile, const char* format, ...)
800   {
801     passert(PortFile);
802 
803     (void)format;
804 
805     /* Not supported. */
806     passert(FALSE);
807     return 0;
808   }
809 
PortRewind(PORT_FILE PortFile)810   void PortRewind(PORT_FILE PortFile)
811   {
812     passert(PortFile);
813 
814     PortFile->curFrame = PortFile->startFrame;
815     PortFile->curPos = PortFile->startFrame->buffer;
816 
817     PortFile->eof = 0;
818   }
819 
820   /*
821    * NULL if it fails, otherwise a valid file pointer
822    */
PortFreopen(const char * path,const char * mode,PORT_FILE PortFile)823   PORT_FILE PortFreopen(const char *path, const char *mode, PORT_FILE PortFile)
824   {
825     /* does not support reopen writable file */
826     if (PortFclose(PortFile) == 0)
827     {
828       PortFile = PortFopen(path, mode);
829       return PortFile;
830     }
831     return NULL;
832   }
833 
PortGetcwd(char * buffer,int maxlen)834   char* PortGetcwd(char *buffer, int maxlen)
835   {
836     if (maxlen >= 1)
837       buffer[0] = '\0';
838     else
839       return NULL;
840 
841     return buffer;
842   }
843 
PortMkdir(const char * dirname)844   int PortMkdir(const char *dirname)
845   {
846     return 0;
847   }
848 
849 #ifdef XANAVI_PROJECT
850 
PortSaveFileToDisk(PORT_FILE PortFile,const char * path,const char * fname)851   int PortSaveFileToDisk(PORT_FILE PortFile, const char *path, const char *fname)
852   {
853     /* ### start mod */
854 
855     FILE *fp = NULL; /* real file handle */
856     char fullfname[256], data[256];
857     char mode[3];
858     const char *file;
859     int size;
860 
861     if (fname == NULL)
862       file = PortFile->filename;
863     else
864       file = fname;
865 
866     if (path == NULL)
867     {
868       PLogMessage("trying to save file %s...\n", file);
869       sprintf(fullfname, "%s", file);
870     }
871     else
872     {
873       PLogMessage("trying to save file %s to %s...\n", file, path);
874       sprintf(fullfname, "%s/%s", path, file);
875     }
876 
877     if (ISBINARYMODE(PortFile->mode))  /* binary file, the wav file */
878     {
879       sprintf(mode, "wb");
880     }
881     else
882     {
883       sprintf(mode, "w");
884     }
885 
886     if ((fp = fopen(fullfname, mode)) != NULL)
887     {
888       PortRewind(PortFile);
889 
890       while ((size = PortFread(data, 1, 256, PortFile)) > 0)
891       {
892         fwrite(data, 1, size, fp);
893       }
894       fclose(fp);
895     }
896     else
897     {
898       PLogError(L("Error to fopen %s with mode %s\n\n"), fullfname, mode);
899       return -1;
900     }
901     return 0;
902   }
903 
PortLoadFileFromDisk(PORT_FILE PortFile,const char * filename,const char * mode)904   int PortLoadFileFromDisk(PORT_FILE PortFile, const char *filename, const char *mode)
905   {
906     FILE *fp;
907     int size;
908     char data[256];
909 
910     passert(PortFile);
911 
912     if (filename == NULL)
913       filename = PortFile->filename;
914 
915     if (mode == NULL)
916     {
917       data[0] = 'r';
918       if (ISBINARYMODE(PortFile->mode))
919         data[1] = 'b';
920       else
921         data[1] = '\0';
922       data[2] = '\0';
923       mode = data;
924     }
925 
926     fp = fopen(filename, mode);
927 
928     if (fp == NULL)   /* do not have the file, it is fine */
929       return 0;
930 
931     while ((size = fread(data, 1, 256, fp)) > 0)
932       PortFwrite(data, 1, size, PortFile);
933 
934     fclose(fp);
935     /* go to the beginning of the file */
936     PortFseek(PortFile, 0, SEEK_SET);
937 
938     return 0;
939   }
940 
XanaviSaveFileToDisk(PORT_FILE PortFile)941   int XanaviSaveFileToDisk(PORT_FILE PortFile)
942   {
943     const char *tail;
944     int lenny;
945 
946     passert(PortFile);
947 
948     /* UG has to be 8.3 format! */
949     lenny = strlen(PortFile->filename);
950     if (lenny > 10)
951       tail = PortFile->filename + (lenny - 11);
952     else
953       tail = PortFile->filename;
954     /* printf( "8.3 filename is %s.\n", tail ); */
955 
956     /* the 8.3 format has truncated the path in PortFile->filename,
957        should get the direcotry from par file
958        cmdline.DataCaptureDirectory                  = /CFC
959        TODO: here use /CFC directly to save time
960     */
961     return PortSaveFileToDisk(PortFile, "/CFC", tail);
962   }
963 
XanaviLoadFileFromDisk(PORT_FILE PortFile)964   int XanaviLoadFileFromDisk(PORT_FILE PortFile)
965   {
966     char fname[256];
967     char mode[3];
968 
969     passert(PortFile);
970 
971     sprintf(fname, "/CFC/%s", PortFile->filename);
972 
973     mode[0] = 'r';
974     if (ISBINARYMODE(PortFile->mode))
975       mode[1] = 'b';
976     else
977       mode[1] = '\0';
978 
979     mode[2] = '\0';
980 
981     return PortLoadFileFromDisk(PortFile, fname, mode);
982   }
983 
984 #endif
985 #endif /* STATIC_FILE_SYSTME */
986 
987 #ifdef __cplusplus
988 }
989 #endif
990 
991