1 /* @(#) pf_save.c 98/01/26 1.3 */
\r
2 /***************************************************************
\r
3 ** Save and Load Dictionary
\r
4 ** for PForth based on 'C'
\r
6 ** Compile file based version or static data based version
\r
7 ** depending on PF_NO_FILEIO switch.
\r
10 ** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom
\r
12 ** The pForth software code is dedicated to the public domain,
\r
13 ** and any third party may reproduce, distribute and modify
\r
14 ** the pForth software code or any derivative works thereof
\r
15 ** without any compensation or license. The pForth software
\r
16 ** code is provided on an "as is" basis without any warranty
\r
17 ** of any kind, including, without limitation, the implied
\r
18 ** warranties of merchantability and fitness for a particular
\r
19 ** purpose and their equivalents under the laws of any jurisdiction.
\r
21 ****************************************************************
\r
22 ** 940225 PLB Fixed CodePtr save, was using NAMEREL instead of CODEREL
\r
23 ** This would only work if the relative location
\r
24 ** of names and code was the same when saved and reloaded.
\r
25 ** 940228 PLB Added PF_NO_FILEIO version
\r
26 ** 961204 PLB Added PF_STATIC_DIC
\r
27 ** 000623 PLB Cast chars as ucell_t before shifting for 16 bit systems.
\r
28 ***************************************************************/
\r
34 /* If no File I/O, then force static dictionary. */
\r
36 #ifndef PF_STATIC_DIC
\r
37 #define PF_STATIC_DIC
\r
41 #ifdef PF_STATIC_DIC
\r
42 #include "pfdicdat.h"
\r
46 Dictionary File Format based on IFF standard.
\r
47 The chunk IDs, sizes, and data values are all Big Endian in conformance with the IFF standard.
\r
48 The dictionaries may be big or little endian.
\r
51 'P4TH' - Form Identifier
\r
56 struct DictionaryInfoChunk
\r
60 Name and Header portion of dictionary. (Big or Little Endian) (Optional)
\r
64 Code portion of dictionary. (Big or Little Endian)
\r
68 /***************************************************************/
\r
69 /* Endian-ness tools. */
\r
70 ucell_t ReadCellBigEndian( const uint8_t *addr )
\r
72 ucell_t temp = (ucell_t)addr[0];
\r
73 temp = (temp << 8) | ((ucell_t)addr[1]);
\r
74 temp = (temp << 8) | ((ucell_t)addr[2]);
\r
75 temp = (temp << 8) | ((ucell_t)addr[3]);
\r
76 if( sizeof(ucell_t) == 8 )
\r
78 temp = (temp << 8) | ((ucell_t)addr[4]);
\r
79 temp = (temp << 8) | ((ucell_t)addr[5]);
\r
80 temp = (temp << 8) | ((ucell_t)addr[6]);
\r
81 temp = (temp << 8) | ((ucell_t)addr[7]);
\r
86 /***************************************************************/
\r
87 /* Endian-ness tools. */
\r
88 uint32_t Read32BigEndian( const uint8_t *addr )
\r
90 uint32_t temp = (uint32_t)addr[0];
\r
91 temp = (temp << 8) | ((uint32_t)addr[1]);
\r
92 temp = (temp << 8) | ((uint32_t)addr[2]);
\r
93 temp = (temp << 8) | ((uint32_t)addr[3]);
\r
97 /***************************************************************/
\r
98 uint16_t Read16BigEndian( const uint8_t *addr )
\r
100 return (uint16_t) ((addr[0]<<8) | addr[1]);
\r
103 /***************************************************************/
\r
104 ucell_t ReadCellLittleEndian( const uint8_t *addr )
\r
107 if( sizeof(ucell_t) == 8 )
\r
109 temp = (temp << 8) | ((uint32_t)addr[7]);
\r
110 temp = (temp << 8) | ((uint32_t)addr[6]);
\r
111 temp = (temp << 8) | ((uint32_t)addr[5]);
\r
112 temp = (temp << 8) | ((uint32_t)addr[4]);
\r
114 temp = (temp << 8) | ((uint32_t)addr[3]);
\r
115 temp = (temp << 8) | ((uint32_t)addr[2]);
\r
116 temp = (temp << 8) | ((uint32_t)addr[1]);
\r
117 temp = (temp << 8) | ((uint32_t)addr[0]);
\r
121 /***************************************************************/
\r
122 uint32_t Read32LittleEndian( const uint8_t *addr )
\r
124 uint32_t temp = (uint32_t)addr[3];
\r
125 temp = (temp << 8) | ((uint32_t)addr[2]);
\r
126 temp = (temp << 8) | ((uint32_t)addr[1]);
\r
127 temp = (temp << 8) | ((uint32_t)addr[0]);
\r
131 /***************************************************************/
\r
132 uint16_t Read16LittleEndian( const uint8_t *addr )
\r
134 const unsigned char *bp = (const unsigned char *) addr;
\r
135 return (uint16_t) ((bp[1]<<8) | bp[0]);
\r
138 #ifdef PF_SUPPORT_FP
\r
140 /***************************************************************/
\r
141 static void ReverseCopyFloat( const PF_FLOAT *src, PF_FLOAT *dst );
\r
143 static void ReverseCopyFloat( const PF_FLOAT *src, PF_FLOAT *dst )
\r
146 unsigned char *d = (unsigned char *) dst;
\r
147 const unsigned char *s = (const unsigned char *) src;
\r
149 for( i=0; i<sizeof(PF_FLOAT); i++ )
\r
151 d[i] = s[sizeof(PF_FLOAT) - 1 - i];
\r
155 /***************************************************************/
\r
156 void WriteFloatBigEndian( PF_FLOAT *addr, PF_FLOAT data )
\r
158 if( IsHostLittleEndian() )
\r
160 ReverseCopyFloat( &data, addr );
\r
168 /***************************************************************/
\r
169 PF_FLOAT ReadFloatBigEndian( const PF_FLOAT *addr )
\r
172 if( IsHostLittleEndian() )
\r
174 ReverseCopyFloat( addr, &data );
\r
183 /***************************************************************/
\r
184 void WriteFloatLittleEndian( PF_FLOAT *addr, PF_FLOAT data )
\r
186 if( IsHostLittleEndian() )
\r
192 ReverseCopyFloat( &data, addr );
\r
196 /***************************************************************/
\r
197 PF_FLOAT ReadFloatLittleEndian( const PF_FLOAT *addr )
\r
200 if( IsHostLittleEndian() )
\r
206 ReverseCopyFloat( addr, &data );
\r
211 #endif /* PF_SUPPORT_FP */
\r
213 /***************************************************************/
\r
214 void WriteCellBigEndian( uint8_t *addr, ucell_t data )
\r
216 // Write should be in order of increasing address
\r
217 // to optimize for burst writes to DRAM.
\r
218 if( sizeof(ucell_t) == 8 )
\r
220 *addr++ = (uint8_t) (data>>56);
\r
221 *addr++ = (uint8_t) (data>>48);
\r
222 *addr++ = (uint8_t) (data>>40);
\r
223 *addr++ = (uint8_t) (data>>32);
\r
225 *addr++ = (uint8_t) (data>>24);
\r
226 *addr++ = (uint8_t) (data>>16);
\r
227 *addr++ = (uint8_t) (data>>8);
\r
228 *addr = (uint8_t) (data);
\r
231 /***************************************************************/
\r
232 void Write32BigEndian( uint8_t *addr, uint32_t data )
\r
234 *addr++ = (uint8_t) (data>>24);
\r
235 *addr++ = (uint8_t) (data>>16);
\r
236 *addr++ = (uint8_t) (data>>8);
\r
237 *addr = (uint8_t) (data);
\r
240 /***************************************************************/
\r
241 void Write16BigEndian( uint8_t *addr, uint16_t data )
\r
243 *addr++ = (uint8_t) (data>>8);
\r
244 *addr = (uint8_t) (data);
\r
247 /***************************************************************/
\r
248 void WriteCellLittleEndian( uint8_t *addr, ucell_t data )
\r
250 // Write should be in order of increasing address
\r
251 // to optimize for burst writes to DRAM.
\r
252 if( sizeof(ucell_t) == 8 )
\r
254 *addr++ = (uint8_t) data; // LSB at near end
\r
256 *addr++ = (uint8_t) data;
\r
258 *addr++ = (uint8_t) data;
\r
260 *addr++ = (uint8_t) data;
\r
263 *addr++ = (uint8_t) data;
\r
265 *addr++ = (uint8_t) data;
\r
267 *addr++ = (uint8_t) data;
\r
269 *addr = (uint8_t) data;
\r
271 /***************************************************************/
\r
272 void Write32LittleEndian( uint8_t *addr, uint32_t data )
\r
274 *addr++ = (uint8_t) data;
\r
276 *addr++ = (uint8_t) data;
\r
278 *addr++ = (uint8_t) data;
\r
280 *addr = (uint8_t) data;
\r
283 /***************************************************************/
\r
284 void Write16LittleEndian( uint8_t *addr, uint16_t data )
\r
286 *addr++ = (uint8_t) data;
\r
288 *addr = (uint8_t) data;
\r
291 /***************************************************************/
\r
292 /* Return 1 if host CPU is Little Endian */
\r
293 int IsHostLittleEndian( void )
\r
295 static int gEndianCheck = 1;
\r
296 unsigned char *bp = (unsigned char *) &gEndianCheck;
\r
297 return (int) (*bp); /* Return byte pointed to by address. If LSB then == 1 */
\r
300 #if defined(PF_NO_FILEIO) || defined(PF_NO_SHELL)
\r
302 cell_t ffSaveForth( const char *FileName, ExecToken EntryPoint, cell_t NameSize, cell_t CodeSize)
\r
309 pfReportError("ffSaveForth", PF_ERR_NOT_SUPPORTED);
\r
313 #else /* PF_NO_FILEIO or PF_NO_SHELL */
\r
315 /***************************************************************/
\r
316 static int Write32ToFile( FileStream *fid, uint32_t Val )
\r
321 Write32BigEndian(pad,Val);
\r
322 numw = sdWriteFile( pad, 1, sizeof(pad), fid );
\r
323 if( numw != sizeof(pad) ) return -1;
\r
327 /***************************************************************/
\r
328 static cell_t WriteChunkToFile( FileStream *fid, cell_t ID, char *Data, int32_t NumBytes )
\r
333 EvenNumW = EVENUP(NumBytes);
\r
335 if( Write32ToFile( fid, ID ) < 0 ) goto error;
\r
336 if( Write32ToFile( fid, EvenNumW ) < 0 ) goto error;
\r
338 numw = sdWriteFile( Data, 1, EvenNumW, fid );
\r
339 if( numw != EvenNumW ) goto error;
\r
342 pfReportError("WriteChunkToFile", PF_ERR_WRITE_FILE);
\r
346 /****************************************************************
\r
347 ** Save Dictionary in File.
\r
348 ** If EntryPoint is NULL, save as development environment.
\r
349 ** If EntryPoint is non-NULL, save as turnKey environment with no names.
\r
351 cell_t ffSaveForth( const char *FileName, ExecToken EntryPoint, cell_t NameSize, cell_t CodeSize)
\r
354 DictionaryInfoChunk SD;
\r
356 uint32_t NameChunkSize = 0;
\r
357 uint32_t CodeChunkSize;
\r
358 uint32_t relativeCodePtr;
\r
361 fid = sdOpenFile( FileName, "wb" );
\r
364 pfReportError("pfSaveDictionary", PF_ERR_OPEN_FILE);
\r
368 /* Save in uninitialized form. */
\r
369 pfExecIfDefined("AUTO.TERM");
\r
371 /* Write FORM Header ---------------------------- */
\r
372 if( Write32ToFile( fid, ID_FORM ) < 0 ) goto error;
\r
373 if( Write32ToFile( fid, 0 ) < 0 ) goto error;
\r
374 if( Write32ToFile( fid, ID_P4TH ) < 0 ) goto error;
\r
376 /* Write P4DI Dictionary Info ------------------ */
\r
377 SD.sd_Version = PF_FILE_VERSION;
\r
379 relativeCodePtr = ABS_TO_CODEREL(gCurrentDictionary->dic_CodePtr.Byte); /* 940225 */
\r
380 SD.sd_RelCodePtr = relativeCodePtr;
\r
381 SD.sd_UserStackSize = sizeof(cell_t) * (gCurrentTask->td_StackBase - gCurrentTask->td_StackLimit);
\r
382 SD.sd_ReturnStackSize = sizeof(cell_t) * (gCurrentTask->td_ReturnBase - gCurrentTask->td_ReturnLimit);
\r
383 SD.sd_NumPrimitives = gNumPrimitives; /* Must match compiled dictionary. */
\r
385 #ifdef PF_SUPPORT_FP
\r
386 SD.sd_FloatSize = sizeof(PF_FLOAT); /* Must match compiled dictionary. */
\r
388 SD.sd_FloatSize = 0;
\r
391 SD.sd_CellSize = sizeof(cell_t);
\r
393 /* Set bit that specifies whether dictionary is BIG or LITTLE Endian. */
\r
395 #if defined(PF_BIG_ENDIAN_DIC)
\r
396 int eflag = SD_F_BIG_ENDIAN_DIC;
\r
397 #elif defined(PF_LITTLE_ENDIAN_DIC)
\r
400 int eflag = IsHostLittleEndian() ? 0 : SD_F_BIG_ENDIAN_DIC;
\r
402 SD.sd_Flags = eflag;
\r
407 SD.sd_EntryPoint = EntryPoint; /* Turnkey! */
\r
411 SD.sd_EntryPoint = 0;
\r
414 /* Do we save names? */
\r
415 if( NameSize == 0 )
\r
417 SD.sd_RelContext = 0;
\r
418 SD.sd_RelHeaderPtr = 0;
\r
419 SD.sd_NameSize = 0;
\r
423 uint32_t relativeHeaderPtr;
\r
424 /* Development mode. */
\r
425 SD.sd_RelContext = ABS_TO_NAMEREL(gVarContext);
\r
426 relativeHeaderPtr = ABS_TO_NAMEREL(gCurrentDictionary->dic_HeaderPtr);
\r
427 SD.sd_RelHeaderPtr = relativeHeaderPtr;
\r
429 /* How much real name space is there? */
\r
430 NameChunkSize = QUADUP(relativeHeaderPtr); /* Align */
\r
432 /* NameSize must be 0 or greater than NameChunkSize + 1K */
\r
433 NameSize = QUADUP(NameSize); /* Align */
\r
436 NameSize = MAX( NameSize, (NameChunkSize + 1024) );
\r
438 SD.sd_NameSize = NameSize;
\r
441 /* How much real code is there? */
\r
442 CodeChunkSize = QUADUP(relativeCodePtr);
\r
443 CodeSize = QUADUP(CodeSize); /* Align */
\r
444 CodeSize = MAX( CodeSize, (CodeChunkSize + 2048) );
\r
445 SD.sd_CodeSize = CodeSize;
\r
448 /* Convert all fields in DictionaryInfoChunk from Native to BigEndian.
\r
449 * This assumes they are all 32-bit integers.
\r
452 uint32_t *p = (uint32_t *) &SD;
\r
453 for( i=0; i<((int)(sizeof(SD)/sizeof(uint32_t))); i++ )
\r
455 Write32BigEndian( (uint8_t *)&p[i], p[i] );
\r
459 if( WriteChunkToFile( fid, ID_P4DI, (char *) &SD, sizeof(DictionaryInfoChunk) ) < 0 ) goto error;
\r
461 /* Write Name Fields if NameSize non-zero ------- */
\r
464 if( WriteChunkToFile( fid, ID_P4NM, (char *) NAME_BASE,
\r
465 NameChunkSize ) < 0 ) goto error;
\r
468 /* Write Code Fields ---------------------------- */
\r
469 if( WriteChunkToFile( fid, ID_P4CD, (char *) CODE_BASE,
\r
470 CodeChunkSize ) < 0 ) goto error;
\r
472 FormSize = sdTellFile( fid ) - 8;
\r
473 sdSeekFile( fid, 4, PF_SEEK_SET );
\r
474 if( Write32ToFile( fid, FormSize ) < 0 ) goto error;
\r
476 sdCloseFile( fid );
\r
478 /* Restore initialization. */
\r
479 pfExecIfDefined("AUTO.INIT");
\r
483 sdSeekFile( fid, 0, PF_SEEK_SET );
\r
484 Write32ToFile( fid, ID_BADF ); /* Mark file as bad. */
\r
485 sdCloseFile( fid );
\r
487 /* Restore initialization. */
\r
488 pfExecIfDefined("AUTO.INIT");
\r
493 #endif /* !PF_NO_FILEIO and !PF_NO_SHELL */
\r
496 #ifndef PF_NO_FILEIO
\r
498 /***************************************************************/
\r
499 static uint32_t Read32FromFile( FileStream *fid, uint32_t *ValPtr )
\r
503 numr = sdReadFile( pad, 1, sizeof(pad), fid );
\r
504 if( numr != sizeof(pad) ) return -1;
\r
505 *ValPtr = Read32BigEndian( pad );
\r
509 /***************************************************************/
\r
510 PForthDictionary pfLoadDictionary( const char *FileName, ExecToken *EntryPointPtr )
\r
512 pfDictionary_t *dic = NULL;
\r
514 DictionaryInfoChunk *sd;
\r
516 uint32_t ChunkSize;
\r
518 uint32_t BytesLeft;
\r
521 int isDicBigEndian;
\r
523 DBUG(("pfLoadDictionary( %s )\n", FileName ));
\r
526 fid = sdOpenFile( FileName, "rb" );
\r
529 pfReportError("pfLoadDictionary", PF_ERR_OPEN_FILE);
\r
533 /* Read FORM, Size, ID */
\r
534 if (Read32FromFile( fid, &ChunkID ) < 0) goto read_error;
\r
535 if( ChunkID != ID_FORM )
\r
537 pfReportError("pfLoadDictionary", PF_ERR_WRONG_FILE);
\r
541 if (Read32FromFile( fid, &FormSize ) < 0) goto read_error;
\r
542 BytesLeft = FormSize;
\r
544 if (Read32FromFile( fid, &ChunkID ) < 0) goto read_error;
\r
546 if( ChunkID != ID_P4TH )
\r
548 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE);
\r
552 /* Scan and parse all chunks in file. */
\r
553 while( BytesLeft > 0 )
\r
555 if (Read32FromFile( fid, &ChunkID ) < 0) goto read_error;
\r
556 if (Read32FromFile( fid, &ChunkSize ) < 0) goto read_error;
\r
559 DBUG(("ChunkID = %4s, Size = %d\n", (char *)&ChunkID, ChunkSize ));
\r
564 sd = (DictionaryInfoChunk *) pfAllocMem( ChunkSize );
\r
565 if( sd == NULL ) goto nomem_error;
\r
567 numr = sdReadFile( sd, 1, ChunkSize, fid );
\r
568 if( numr != ChunkSize ) goto read_error;
\r
569 BytesLeft -= ChunkSize;
\r
571 /* Convert all fields in structure from BigEndian to Native. */
\r
573 uint32_t *p = (uint32_t *) sd;
\r
574 for( i=0; i<((int)(sizeof(*sd)/sizeof(uint32_t))); i++ )
\r
576 p[i] = Read32BigEndian( (uint8_t *)&p[i] );
\r
580 isDicBigEndian = sd->sd_Flags & SD_F_BIG_ENDIAN_DIC;
\r
584 MSG("pForth loading dictionary from file "); MSG(FileName);
\r
586 MSG_NUM_D(" File format version is ", sd->sd_Version );
\r
587 MSG_NUM_D(" Name space size = ", sd->sd_NameSize );
\r
588 MSG_NUM_D(" Code space size = ", sd->sd_CodeSize );
\r
589 MSG_NUM_D(" Entry Point = ", sd->sd_EntryPoint );
\r
590 MSG_NUM_D(" Cell Size = ", sd->sd_CellSize );
\r
591 MSG( (isDicBigEndian ? " Big Endian Dictionary" :
\r
592 " Little Endian Dictionary") );
\r
593 if( isDicBigEndian == IsHostLittleEndian() ) MSG(" !!!!");
\r
597 if( sd->sd_Version > PF_FILE_VERSION )
\r
599 pfReportError("pfLoadDictionary", PF_ERR_VERSION_FUTURE );
\r
602 if( sd->sd_Version < PF_EARLIEST_FILE_VERSION )
\r
604 pfReportError("pfLoadDictionary", PF_ERR_VERSION_PAST );
\r
607 if( sd->sd_CellSize != sizeof(cell_t) )
\r
609 pfReportError("pfLoadDictionary", PF_ERR_CELL_SIZE_CONFLICT );
\r
612 if( sd->sd_NumPrimitives > NUM_PRIMITIVES )
\r
614 pfReportError("pfLoadDictionary", PF_ERR_NOT_SUPPORTED );
\r
618 /* Check to make sure that EndianNess of dictionary matches mode of pForth. */
\r
619 #if defined(PF_BIG_ENDIAN_DIC)
\r
620 if(isDicBigEndian == 0)
\r
621 #elif defined(PF_LITTLE_ENDIAN_DIC)
\r
622 if(isDicBigEndian == 1)
\r
624 if( isDicBigEndian == IsHostLittleEndian() )
\r
627 pfReportError("pfLoadDictionary", PF_ERR_ENDIAN_CONFLICT );
\r
631 /* Check for compatible float size. */
\r
632 #ifdef PF_SUPPORT_FP
\r
633 if( sd->sd_FloatSize != sizeof(PF_FLOAT) )
\r
635 if( sd->sd_FloatSize != 0 )
\r
638 pfReportError("pfLoadDictionary", PF_ERR_FLOAT_CONFLICT );
\r
642 dic = pfCreateDictionary( sd->sd_NameSize, sd->sd_CodeSize );
\r
643 if( dic == NULL ) goto nomem_error;
\r
644 gCurrentDictionary = dic;
\r
645 if( sd->sd_NameSize > 0 )
\r
647 gVarContext = (char *) NAMEREL_TO_ABS(sd->sd_RelContext); /* Restore context. */
\r
648 gCurrentDictionary->dic_HeaderPtr = (ucell_t)(uint8_t *)
\r
649 NAMEREL_TO_ABS(sd->sd_RelHeaderPtr);
\r
654 gCurrentDictionary->dic_HeaderPtr = (ucell_t)NULL;
\r
656 gCurrentDictionary->dic_CodePtr.Byte = (uint8_t *) CODEREL_TO_ABS(sd->sd_RelCodePtr);
\r
657 gNumPrimitives = sd->sd_NumPrimitives; /* Must match compiled dictionary. */
\r
658 /* Pass EntryPoint back to caller. */
\r
659 if( EntryPointPtr != NULL ) *EntryPointPtr = sd->sd_EntryPoint;
\r
665 pfReportError("pfLoadDictionary", PF_ERR_NO_SHELL );
\r
668 if( NAME_BASE == NULL )
\r
670 pfReportError("pfLoadDictionary", PF_ERR_NO_NAMES );
\r
673 if( gCurrentDictionary == NULL )
\r
675 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
\r
678 if( ChunkSize > NAME_SIZE )
\r
680 pfReportError("pfLoadDictionary", PF_ERR_TOO_BIG);
\r
683 numr = sdReadFile( NAME_BASE, 1, ChunkSize, fid );
\r
684 if( numr != ChunkSize ) goto read_error;
\r
685 BytesLeft -= ChunkSize;
\r
686 #endif /* PF_NO_SHELL */
\r
690 if( gCurrentDictionary == NULL )
\r
692 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
\r
695 if( ChunkSize > CODE_SIZE )
\r
697 pfReportError("pfLoadDictionary", PF_ERR_TOO_BIG);
\r
700 numr = sdReadFile( CODE_BASE, 1, ChunkSize, fid );
\r
701 if( numr != ChunkSize ) goto read_error;
\r
702 BytesLeft -= ChunkSize;
\r
706 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
\r
707 sdSeekFile( fid, ChunkSize, PF_SEEK_CUR );
\r
712 sdCloseFile( fid );
\r
714 if( NAME_BASE != NULL)
\r
717 /* Find special words in dictionary for global XTs. */
\r
718 if( (Result = FindSpecialXTs()) < 0 )
\r
720 pfReportError("pfLoadDictionary: FindSpecialXTs", Result);
\r
725 DBUG(("pfLoadDictionary: return %p\n", dic));
\r
726 return (PForthDictionary) dic;
\r
729 pfReportError("pfLoadDictionary", PF_ERR_NO_MEM);
\r
730 sdCloseFile( fid );
\r
734 pfReportError("pfLoadDictionary", PF_ERR_READ_FILE);
\r
736 sdCloseFile( fid );
\r
743 PForthDictionary pfLoadDictionary( const char *FileName, ExecToken *EntryPointPtr )
\r
746 (void) EntryPointPtr;
\r
749 #endif /* !PF_NO_FILEIO */
\r
753 /***************************************************************/
\r
754 PForthDictionary pfLoadStaticDictionary( void )
\r
756 #ifdef PF_STATIC_DIC
\r
758 pfDictionary_t *dic;
\r
759 cell_t NewNameSize, NewCodeSize;
\r
761 if( IF_LITTLE_ENDIAN != IsHostLittleEndian() )
\r
763 MSG( (IF_LITTLE_ENDIAN ?
\r
764 "Little Endian Dictionary on " :
\r
765 "Big Endian Dictionary on ") );
\r
766 MSG( (IsHostLittleEndian() ?
\r
767 "Little Endian CPU" :
\r
768 "Big Endian CPU") );
\r
772 /* Check to make sure that EndianNess of dictionary matches mode of pForth. */
\r
773 #if defined(PF_BIG_ENDIAN_DIC)
\r
774 if(IF_LITTLE_ENDIAN == 1)
\r
775 #elif defined(PF_LITTLE_ENDIAN_DIC)
\r
776 if(IF_LITTLE_ENDIAN == 0)
\r
777 #else /* Code is native endian! */
\r
778 if( IF_LITTLE_ENDIAN != IsHostLittleEndian() )
\r
781 pfReportError("pfLoadStaticDictionary", PF_ERR_ENDIAN_CONFLICT );
\r
786 #ifndef PF_EXTRA_HEADERS
\r
787 #define PF_EXTRA_HEADERS (20000)
\r
789 #ifndef PF_EXTRA_CODE
\r
790 #define PF_EXTRA_CODE (40000)
\r
793 /* Copy static const data to allocated dictionaries. */
\r
794 NewNameSize = sizeof(MinDicNames) + PF_EXTRA_HEADERS;
\r
795 NewCodeSize = sizeof(MinDicCode) + PF_EXTRA_CODE;
\r
797 DBUG_NUM_D( "static dic name size = ", NewNameSize );
\r
798 DBUG_NUM_D( "static dic code size = ", NewCodeSize );
\r
800 gCurrentDictionary = dic = pfCreateDictionary( NewNameSize, NewCodeSize );
\r
801 if( !dic ) goto nomem_error;
\r
803 pfCopyMemory( dic->dic_HeaderBase, MinDicNames, sizeof(MinDicNames) );
\r
804 pfCopyMemory( dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode) );
\r
805 DBUG(("Static data copied to newly allocated dictionaries.\n"));
\r
807 dic->dic_CodePtr.Byte = (uint8_t *) CODEREL_TO_ABS(CODEPTR);
\r
808 gNumPrimitives = NUM_PRIMITIVES;
\r
810 if( NAME_BASE != NULL)
\r
812 /* Setup name space. */
\r
813 dic->dic_HeaderPtr = (ucell_t)(uint8_t *) NAMEREL_TO_ABS(HEADERPTR);
\r
814 gVarContext = (char *) NAMEREL_TO_ABS(RELCONTEXT); /* Restore context. */
\r
816 /* Find special words in dictionary for global XTs. */
\r
817 if( (Result = FindSpecialXTs()) < 0 )
\r
819 pfReportError("pfLoadStaticDictionary: FindSpecialXTs", Result);
\r
824 return (PForthDictionary) dic;
\r
830 pfReportError("pfLoadStaticDictionary", PF_ERR_NO_MEM);
\r
831 #endif /* PF_STATIC_DIC */
\r