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 /* Convert dictionary info chunk between native and on-disk (big-endian). */
\r
348 convertDictionaryInfoWrite (DictionaryInfoChunk *sd)
\r
350 /* Convert all fields in DictionaryInfoChunk from Native to BigEndian.
\r
351 * This assumes they are all 32-bit integers.
\r
354 uint32_t *p = (uint32_t *) sd;
\r
355 for (i=0; i<((int)(sizeof(*sd)/sizeof(uint32_t))); i++)
\r
357 Write32BigEndian( (uint8_t *)&p[i], p[i] );
\r
362 convertDictionaryInfoRead (DictionaryInfoChunk *sd)
\r
364 /* Convert all fields in structure from BigEndian to Native. */
\r
366 uint32_t *p = (uint32_t *) sd;
\r
367 for (i=0; i<((int)(sizeof(*sd)/sizeof(uint32_t))); i++)
\r
369 p[i] = Read32BigEndian( (uint8_t *)&p[i] );
\r
373 /****************************************************************
\r
374 ** Save Dictionary in File.
\r
375 ** If EntryPoint is NULL, save as development environment.
\r
376 ** If EntryPoint is non-NULL, save as turnKey environment with no names.
\r
378 cell_t ffSaveForth( const char *FileName, ExecToken EntryPoint, cell_t NameSize, cell_t CodeSize)
\r
381 DictionaryInfoChunk SD;
\r
383 uint32_t NameChunkSize = 0;
\r
384 uint32_t CodeChunkSize;
\r
385 uint32_t relativeCodePtr;
\r
387 fid = sdOpenFile( FileName, "wb" );
\r
390 pfReportError("pfSaveDictionary", PF_ERR_OPEN_FILE);
\r
394 /* Save in uninitialized form. */
\r
395 pfExecIfDefined("AUTO.TERM");
\r
397 /* Write FORM Header ---------------------------- */
\r
398 if( Write32ToFile( fid, ID_FORM ) < 0 ) goto error;
\r
399 if( Write32ToFile( fid, 0 ) < 0 ) goto error;
\r
400 if( Write32ToFile( fid, ID_P4TH ) < 0 ) goto error;
\r
402 /* Write P4DI Dictionary Info ------------------ */
\r
403 SD.sd_Version = PF_FILE_VERSION;
\r
405 relativeCodePtr = ABS_TO_CODEREL(gCurrentDictionary->dic_CodePtr.Byte); /* 940225 */
\r
406 SD.sd_RelCodePtr = relativeCodePtr;
\r
407 SD.sd_UserStackSize = sizeof(cell_t) * (gCurrentTask->td_StackBase - gCurrentTask->td_StackLimit);
\r
408 SD.sd_ReturnStackSize = sizeof(cell_t) * (gCurrentTask->td_ReturnBase - gCurrentTask->td_ReturnLimit);
\r
409 SD.sd_NumPrimitives = gNumPrimitives; /* Must match compiled dictionary. */
\r
411 #ifdef PF_SUPPORT_FP
\r
412 SD.sd_FloatSize = sizeof(PF_FLOAT); /* Must match compiled dictionary. */
\r
414 SD.sd_FloatSize = 0;
\r
417 SD.sd_CellSize = sizeof(cell_t);
\r
419 /* Set bit that specifies whether dictionary is BIG or LITTLE Endian. */
\r
421 #if defined(PF_BIG_ENDIAN_DIC)
\r
422 int eflag = SD_F_BIG_ENDIAN_DIC;
\r
423 #elif defined(PF_LITTLE_ENDIAN_DIC)
\r
426 int eflag = IsHostLittleEndian() ? 0 : SD_F_BIG_ENDIAN_DIC;
\r
428 SD.sd_Flags = eflag;
\r
433 SD.sd_EntryPoint = EntryPoint; /* Turnkey! */
\r
437 SD.sd_EntryPoint = 0;
\r
440 /* Do we save names? */
\r
441 if( NameSize == 0 )
\r
443 SD.sd_RelContext = 0;
\r
444 SD.sd_RelHeaderPtr = 0;
\r
445 SD.sd_NameSize = 0;
\r
449 uint32_t relativeHeaderPtr;
\r
450 /* Development mode. */
\r
451 SD.sd_RelContext = ABS_TO_NAMEREL(gVarContext);
\r
452 relativeHeaderPtr = ABS_TO_NAMEREL(gCurrentDictionary->dic_HeaderPtr);
\r
453 SD.sd_RelHeaderPtr = relativeHeaderPtr;
\r
455 /* How much real name space is there? */
\r
456 NameChunkSize = QUADUP(relativeHeaderPtr); /* Align */
\r
458 /* NameSize must be 0 or greater than NameChunkSize + 1K */
\r
459 NameSize = QUADUP(NameSize); /* Align */
\r
462 NameSize = MAX( NameSize, (NameChunkSize + 1024) );
\r
464 SD.sd_NameSize = NameSize;
\r
467 /* How much real code is there? */
\r
468 CodeChunkSize = QUADUP(relativeCodePtr);
\r
469 CodeSize = QUADUP(CodeSize); /* Align */
\r
470 CodeSize = MAX( CodeSize, (CodeChunkSize + 2048) );
\r
471 SD.sd_CodeSize = CodeSize;
\r
474 convertDictionaryInfoWrite (&SD);
\r
476 if( WriteChunkToFile( fid, ID_P4DI, (char *) &SD, sizeof(DictionaryInfoChunk) ) < 0 ) goto error;
\r
478 /* Write Name Fields if NameSize non-zero ------- */
\r
481 if( WriteChunkToFile( fid, ID_P4NM, (char *) NAME_BASE,
\r
482 NameChunkSize ) < 0 ) goto error;
\r
485 /* Write Code Fields ---------------------------- */
\r
486 if( WriteChunkToFile( fid, ID_P4CD, (char *) CODE_BASE,
\r
487 CodeChunkSize ) < 0 ) goto error;
\r
489 FormSize = sdTellFile( fid ) - 8;
\r
490 sdSeekFile( fid, 4, PF_SEEK_SET );
\r
491 if( Write32ToFile( fid, FormSize ) < 0 ) goto error;
\r
493 sdCloseFile( fid );
\r
495 /* Restore initialization. */
\r
496 pfExecIfDefined("AUTO.INIT");
\r
500 sdSeekFile( fid, 0, PF_SEEK_SET );
\r
501 Write32ToFile( fid, ID_BADF ); /* Mark file as bad. */
\r
502 sdCloseFile( fid );
\r
504 /* Restore initialization. */
\r
505 pfExecIfDefined("AUTO.INIT");
\r
510 #endif /* !PF_NO_FILEIO and !PF_NO_SHELL */
\r
513 #ifndef PF_NO_FILEIO
\r
515 /***************************************************************/
\r
516 static uint32_t Read32FromFile( FileStream *fid, uint32_t *ValPtr )
\r
520 numr = sdReadFile( pad, 1, sizeof(pad), fid );
\r
521 if( numr != sizeof(pad) ) return -1;
\r
522 *ValPtr = Read32BigEndian( pad );
\r
526 /***************************************************************/
\r
527 PForthDictionary pfLoadDictionary( const char *FileName, ExecToken *EntryPointPtr )
\r
529 pfDictionary_t *dic = NULL;
\r
531 DictionaryInfoChunk *sd;
\r
533 uint32_t ChunkSize;
\r
535 uint32_t BytesLeft;
\r
537 int isDicBigEndian;
\r
539 DBUG(("pfLoadDictionary( %s )\n", FileName ));
\r
542 fid = sdOpenFile( FileName, "rb" );
\r
545 pfReportError("pfLoadDictionary", PF_ERR_OPEN_FILE);
\r
549 /* Read FORM, Size, ID */
\r
550 if (Read32FromFile( fid, &ChunkID ) < 0) goto read_error;
\r
551 if( ChunkID != ID_FORM )
\r
553 pfReportError("pfLoadDictionary", PF_ERR_WRONG_FILE);
\r
557 if (Read32FromFile( fid, &FormSize ) < 0) goto read_error;
\r
558 BytesLeft = FormSize;
\r
560 if (Read32FromFile( fid, &ChunkID ) < 0) goto read_error;
\r
562 if( ChunkID != ID_P4TH )
\r
564 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE);
\r
568 /* Scan and parse all chunks in file. */
\r
569 while( BytesLeft > 0 )
\r
571 if (Read32FromFile( fid, &ChunkID ) < 0) goto read_error;
\r
572 if (Read32FromFile( fid, &ChunkSize ) < 0) goto read_error;
\r
575 DBUG(("ChunkID = %4s, Size = %d\n", (char *)&ChunkID, ChunkSize ));
\r
580 sd = (DictionaryInfoChunk *) pfAllocMem( ChunkSize );
\r
581 if( sd == NULL ) goto nomem_error;
\r
583 numr = sdReadFile( sd, 1, ChunkSize, fid );
\r
584 if( numr != ChunkSize ) goto read_error;
\r
585 BytesLeft -= ChunkSize;
\r
587 convertDictionaryInfoRead (sd);
\r
589 isDicBigEndian = sd->sd_Flags & SD_F_BIG_ENDIAN_DIC;
\r
593 MSG("pForth loading dictionary from file "); MSG(FileName);
\r
595 MSG_NUM_D(" File format version is ", sd->sd_Version );
\r
596 MSG_NUM_D(" Name space size = ", sd->sd_NameSize );
\r
597 MSG_NUM_D(" Code space size = ", sd->sd_CodeSize );
\r
598 MSG_NUM_D(" Entry Point = ", sd->sd_EntryPoint );
\r
599 MSG_NUM_D(" Cell Size = ", sd->sd_CellSize );
\r
600 MSG( (isDicBigEndian ? " Big Endian Dictionary" :
\r
601 " Little Endian Dictionary") );
\r
602 if( isDicBigEndian == IsHostLittleEndian() ) MSG(" !!!!");
\r
606 if( sd->sd_Version > PF_FILE_VERSION )
\r
608 pfReportError("pfLoadDictionary", PF_ERR_VERSION_FUTURE );
\r
611 if( sd->sd_Version < PF_EARLIEST_FILE_VERSION )
\r
613 pfReportError("pfLoadDictionary", PF_ERR_VERSION_PAST );
\r
616 if( sd->sd_CellSize != sizeof(cell_t) )
\r
618 pfReportError("pfLoadDictionary", PF_ERR_CELL_SIZE_CONFLICT );
\r
621 if( sd->sd_NumPrimitives > NUM_PRIMITIVES )
\r
623 pfReportError("pfLoadDictionary", PF_ERR_NOT_SUPPORTED );
\r
627 /* Check to make sure that EndianNess of dictionary matches mode of pForth. */
\r
628 #if defined(PF_BIG_ENDIAN_DIC)
\r
629 if(isDicBigEndian == 0)
\r
630 #elif defined(PF_LITTLE_ENDIAN_DIC)
\r
631 if(isDicBigEndian == 1)
\r
633 if( isDicBigEndian == IsHostLittleEndian() )
\r
636 pfReportError("pfLoadDictionary", PF_ERR_ENDIAN_CONFLICT );
\r
640 /* Check for compatible float size. */
\r
641 #ifdef PF_SUPPORT_FP
\r
642 if( sd->sd_FloatSize != sizeof(PF_FLOAT) )
\r
644 if( sd->sd_FloatSize != 0 )
\r
647 pfReportError("pfLoadDictionary", PF_ERR_FLOAT_CONFLICT );
\r
651 dic = pfCreateDictionary( sd->sd_NameSize, sd->sd_CodeSize );
\r
652 if( dic == NULL ) goto nomem_error;
\r
653 gCurrentDictionary = dic;
\r
654 if( sd->sd_NameSize > 0 )
\r
656 gVarContext = (char *) NAMEREL_TO_ABS(sd->sd_RelContext); /* Restore context. */
\r
657 gCurrentDictionary->dic_HeaderPtr = (ucell_t)(uint8_t *)
\r
658 NAMEREL_TO_ABS(sd->sd_RelHeaderPtr);
\r
663 gCurrentDictionary->dic_HeaderPtr = (ucell_t)NULL;
\r
665 gCurrentDictionary->dic_CodePtr.Byte = (uint8_t *) CODEREL_TO_ABS(sd->sd_RelCodePtr);
\r
666 gNumPrimitives = sd->sd_NumPrimitives; /* Must match compiled dictionary. */
\r
667 /* Pass EntryPoint back to caller. */
\r
668 if( EntryPointPtr != NULL ) *EntryPointPtr = sd->sd_EntryPoint;
\r
674 pfReportError("pfLoadDictionary", PF_ERR_NO_SHELL );
\r
677 if( NAME_BASE == NULL )
\r
679 pfReportError("pfLoadDictionary", PF_ERR_NO_NAMES );
\r
682 if( gCurrentDictionary == NULL )
\r
684 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
\r
687 if( ChunkSize > NAME_SIZE )
\r
689 pfReportError("pfLoadDictionary", PF_ERR_TOO_BIG);
\r
692 numr = sdReadFile( NAME_BASE, 1, ChunkSize, fid );
\r
693 if( numr != ChunkSize ) goto read_error;
\r
694 BytesLeft -= ChunkSize;
\r
695 #endif /* PF_NO_SHELL */
\r
699 if( gCurrentDictionary == NULL )
\r
701 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
\r
704 if( ChunkSize > CODE_SIZE )
\r
706 pfReportError("pfLoadDictionary", PF_ERR_TOO_BIG);
\r
709 numr = sdReadFile( CODE_BASE, 1, ChunkSize, fid );
\r
710 if( numr != ChunkSize ) goto read_error;
\r
711 BytesLeft -= ChunkSize;
\r
715 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
\r
716 sdSeekFile( fid, ChunkSize, PF_SEEK_CUR );
\r
721 sdCloseFile( fid );
\r
723 if( NAME_BASE != NULL)
\r
726 /* Find special words in dictionary for global XTs. */
\r
727 if( (Result = FindSpecialXTs()) < 0 )
\r
729 pfReportError("pfLoadDictionary: FindSpecialXTs", Result);
\r
734 DBUG(("pfLoadDictionary: return %p\n", dic));
\r
735 return (PForthDictionary) dic;
\r
738 pfReportError("pfLoadDictionary", PF_ERR_NO_MEM);
\r
739 sdCloseFile( fid );
\r
743 pfReportError("pfLoadDictionary", PF_ERR_READ_FILE);
\r
745 sdCloseFile( fid );
\r
752 PForthDictionary pfLoadDictionary( const char *FileName, ExecToken *EntryPointPtr )
\r
755 (void) EntryPointPtr;
\r
758 #endif /* !PF_NO_FILEIO */
\r
762 /***************************************************************/
\r
763 PForthDictionary pfLoadStaticDictionary( void )
\r
765 #ifdef PF_STATIC_DIC
\r
767 pfDictionary_t *dic;
\r
768 cell_t NewNameSize, NewCodeSize;
\r
770 if( IF_LITTLE_ENDIAN != IsHostLittleEndian() )
\r
772 MSG( (IF_LITTLE_ENDIAN ?
\r
773 "Little Endian Dictionary on " :
\r
774 "Big Endian Dictionary on ") );
\r
775 MSG( (IsHostLittleEndian() ?
\r
776 "Little Endian CPU" :
\r
777 "Big Endian CPU") );
\r
781 /* Check to make sure that EndianNess of dictionary matches mode of pForth. */
\r
782 #if defined(PF_BIG_ENDIAN_DIC)
\r
783 if(IF_LITTLE_ENDIAN == 1)
\r
784 #elif defined(PF_LITTLE_ENDIAN_DIC)
\r
785 if(IF_LITTLE_ENDIAN == 0)
\r
786 #else /* Code is native endian! */
\r
787 if( IF_LITTLE_ENDIAN != IsHostLittleEndian() )
\r
790 pfReportError("pfLoadStaticDictionary", PF_ERR_ENDIAN_CONFLICT );
\r
795 #ifndef PF_EXTRA_HEADERS
\r
796 #define PF_EXTRA_HEADERS (20000)
\r
798 #ifndef PF_EXTRA_CODE
\r
799 #define PF_EXTRA_CODE (40000)
\r
802 /* Copy static const data to allocated dictionaries. */
\r
803 NewNameSize = sizeof(MinDicNames) + PF_EXTRA_HEADERS;
\r
804 NewCodeSize = sizeof(MinDicCode) + PF_EXTRA_CODE;
\r
806 DBUG_NUM_D( "static dic name size = ", NewNameSize );
\r
807 DBUG_NUM_D( "static dic code size = ", NewCodeSize );
\r
809 gCurrentDictionary = dic = pfCreateDictionary( NewNameSize, NewCodeSize );
\r
810 if( !dic ) goto nomem_error;
\r
812 pfCopyMemory( dic->dic_HeaderBase, MinDicNames, sizeof(MinDicNames) );
\r
813 pfCopyMemory( dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode) );
\r
814 DBUG(("Static data copied to newly allocated dictionaries.\n"));
\r
816 dic->dic_CodePtr.Byte = (uint8_t *) CODEREL_TO_ABS(CODEPTR);
\r
817 gNumPrimitives = NUM_PRIMITIVES;
\r
819 if( NAME_BASE != NULL)
\r
821 /* Setup name space. */
\r
822 dic->dic_HeaderPtr = (ucell_t)(uint8_t *) NAMEREL_TO_ABS(HEADERPTR);
\r
823 gVarContext = (char *) NAMEREL_TO_ABS(RELCONTEXT); /* Restore context. */
\r
825 /* Find special words in dictionary for global XTs. */
\r
826 if( (Result = FindSpecialXTs()) < 0 )
\r
828 pfReportError("pfLoadStaticDictionary: FindSpecialXTs", Result);
\r
833 return (PForthDictionary) dic;
\r
839 pfReportError("pfLoadStaticDictionary", PF_ERR_NO_MEM);
\r
840 #endif /* PF_STATIC_DIC */
\r