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 uint32 before shifting for 16 bit systems.
\r
28 ***************************************************************/
\r
32 /* If no File I/O, then force static dictionary. */
\r
34 #ifndef PF_STATIC_DIC
\r
35 #define PF_STATIC_DIC
\r
39 #ifdef PF_STATIC_DIC
\r
40 #include "pfdicdat.h"
\r
44 Dictionary File Format based on IFF standard.
\r
45 The chunk IDs, sizes, and data values are all Big Endian in conformance with the IFF standard.
\r
46 The dictionaries may be big or little endian.
\r
49 'P4TH' - Form Identifier
\r
54 struct DictionaryInfoChunk
\r
58 Name and Header portion of dictionary. (Big or Little Endian) (Optional)
\r
62 Code portion of dictionary. (Big or Little Endian)
\r
66 /***************************************************************/
\r
67 /* Endian-ness tools. */
\r
68 uint32 ReadLongBigEndian( const uint32 *addr )
\r
70 const unsigned char *bp = (const unsigned char *) addr;
\r
71 /* We must cast char to uint32 before shifting because
\r
72 ** of systems with 16 bit ints. 000623 */
\r
73 uint32 temp = ((uint32)bp[0])<<24;
\r
74 temp |= ((uint32)bp[1])<<16;
\r
75 temp |= ((uint32)bp[2])<<8;
\r
76 temp |= ((uint32)bp[3]);
\r
79 /***************************************************************/
\r
80 uint16 ReadShortBigEndian( const uint16 *addr )
\r
82 const unsigned char *bp = (const unsigned char *) addr;
\r
83 return (uint16) ((bp[0]<<8) | bp[1]);
\r
86 /***************************************************************/
\r
87 uint32 ReadLongLittleEndian( const uint32 *addr )
\r
89 const unsigned char *bp = (const unsigned char *) addr;
\r
90 /* We must cast char to uint32 before shifting because
\r
91 ** of systems with 16 bit ints. 000623 */
\r
92 uint32 temp = ((uint32)bp[3])<<24;
\r
93 temp |= ((uint32)bp[2])<<16;
\r
94 temp |= ((uint32)bp[1])<<8;
\r
95 temp |= ((uint32)bp[0]);
\r
98 /***************************************************************/
\r
99 uint16 ReadShortLittleEndian( const uint16 *addr )
\r
101 const unsigned char *bp = (const unsigned char *) addr;
\r
102 return (uint16) ((bp[1]<<8) | bp[0]);
\r
105 #ifdef PF_SUPPORT_FP
\r
107 /***************************************************************/
\r
108 static void ReverseCopyFloat( const PF_FLOAT *src, PF_FLOAT *dst );
\r
110 static void ReverseCopyFloat( const PF_FLOAT *src, PF_FLOAT *dst )
\r
113 unsigned char *d = (unsigned char *) dst;
\r
114 const unsigned char *s = (const unsigned char *) src;
\r
116 for( i=0; i<sizeof(PF_FLOAT); i++ )
\r
118 d[i] = s[sizeof(PF_FLOAT) - 1 - i];
\r
122 /***************************************************************/
\r
123 void WriteFloatBigEndian( PF_FLOAT *addr, PF_FLOAT data )
\r
125 if( IsHostLittleEndian() )
\r
127 ReverseCopyFloat( &data, addr );
\r
135 /***************************************************************/
\r
136 PF_FLOAT ReadFloatBigEndian( const PF_FLOAT *addr )
\r
139 if( IsHostLittleEndian() )
\r
141 ReverseCopyFloat( addr, &data );
\r
150 /***************************************************************/
\r
151 void WriteFloatLittleEndian( PF_FLOAT *addr, PF_FLOAT data )
\r
153 if( IsHostLittleEndian() )
\r
159 ReverseCopyFloat( &data, addr );
\r
163 /***************************************************************/
\r
164 PF_FLOAT ReadFloatLittleEndian( const PF_FLOAT *addr )
\r
167 if( IsHostLittleEndian() )
\r
173 ReverseCopyFloat( addr, &data );
\r
178 #endif /* PF_SUPPORT_FP */
\r
180 /***************************************************************/
\r
181 void WriteLongBigEndian( uint32 *addr, uint32 data )
\r
183 unsigned char *bp = (unsigned char *) addr;
\r
185 bp[0] = (unsigned char) (data>>24);
\r
186 bp[1] = (unsigned char) (data>>16);
\r
187 bp[2] = (unsigned char) (data>>8);
\r
188 bp[3] = (unsigned char) (data);
\r
191 /***************************************************************/
\r
192 void WriteShortBigEndian( uint16 *addr, uint16 data )
\r
194 unsigned char *bp = (unsigned char *) addr;
\r
196 bp[0] = (unsigned char) (data>>8);
\r
197 bp[1] = (unsigned char) (data);
\r
200 /***************************************************************/
\r
201 void WriteLongLittleEndian( uint32 *addr, uint32 data )
\r
203 unsigned char *bp = (unsigned char *) addr;
\r
205 bp[0] = (unsigned char) (data);
\r
206 bp[1] = (unsigned char) (data>>8);
\r
207 bp[2] = (unsigned char) (data>>16);
\r
208 bp[3] = (unsigned char) (data>>24);
\r
210 /***************************************************************/
\r
211 void WriteShortLittleEndian( uint16 *addr, uint16 data )
\r
213 unsigned char *bp = (unsigned char *) addr;
\r
215 bp[0] = (unsigned char) (data);
\r
216 bp[1] = (unsigned char) (data>>8);
\r
219 /***************************************************************/
\r
220 /* Return 1 if host CPU is Little Endian */
\r
221 int IsHostLittleEndian( void )
\r
223 static int gEndianCheck = 1;
\r
224 unsigned char *bp = (unsigned char *) &gEndianCheck;
\r
225 return (int) (*bp); /* Return byte pointed to by address. If LSB then == 1 */
\r
228 #if defined(PF_NO_FILEIO) || defined(PF_NO_SHELL)
\r
230 int32 ffSaveForth( const char *FileName, ExecToken EntryPoint, int32 NameSize, int32 CodeSize)
\r
237 pfReportError("ffSaveForth", PF_ERR_NOT_SUPPORTED);
\r
241 #else /* PF_NO_FILEIO or PF_NO_SHELL */
\r
243 /***************************************************************/
\r
244 static int32 WriteLong( FileStream *fid, int32 Val )
\r
249 WriteLongBigEndian(&pad,Val);
\r
250 numw = sdWriteFile( (char *) &pad, 1, sizeof(int32), fid );
\r
251 if( numw != sizeof(int32) ) return -1;
\r
255 /***************************************************************/
\r
256 static int32 WriteChunk( FileStream *fid, int32 ID, char *Data, int32 NumBytes )
\r
261 EvenNumW = EVENUP(NumBytes);
\r
263 if( WriteLong( fid, ID ) < 0 ) goto error;
\r
264 if( WriteLong( fid, EvenNumW ) < 0 ) goto error;
\r
266 numw = sdWriteFile( Data, 1, EvenNumW, fid );
\r
267 if( numw != EvenNumW ) goto error;
\r
270 pfReportError("WriteChunk", PF_ERR_WRITE_FILE);
\r
274 /****************************************************************
\r
275 ** Save Dictionary in File.
\r
276 ** If EntryPoint is NULL, save as development environment.
\r
277 ** If EntryPoint is non-NULL, save as turnKey environment with no names.
\r
279 int32 ffSaveForth( const char *FileName, ExecToken EntryPoint, int32 NameSize, int32 CodeSize)
\r
282 DictionaryInfoChunk SD;
\r
284 int32 NameChunkSize = 0;
\r
285 int32 CodeChunkSize;
\r
290 fid = sdOpenFile( FileName, "wb" );
\r
293 pfReportError("pfSaveDictionary", PF_ERR_OPEN_FILE);
\r
297 /* Save in uninitialized form. */
\r
298 pfExecIfDefined("AUTO.TERM");
\r
300 /* Write FORM Header ---------------------------- */
\r
301 if( WriteLong( fid, ID_FORM ) < 0 ) goto error;
\r
302 if( WriteLong( fid, 0 ) < 0 ) goto error;
\r
303 if( WriteLong( fid, ID_P4TH ) < 0 ) goto error;
\r
305 /* Write P4DI Dictionary Info ------------------ */
\r
306 SD.sd_Version = PF_FILE_VERSION;
\r
308 rcp = ABS_TO_CODEREL(gCurrentDictionary->dic_CodePtr.Byte); /* 940225 */
\r
309 SD.sd_RelCodePtr = rcp;
\r
310 SD.sd_UserStackSize = sizeof(cell) * (gCurrentTask->td_StackBase - gCurrentTask->td_StackLimit);
\r
311 SD.sd_ReturnStackSize = sizeof(cell) * (gCurrentTask->td_ReturnBase - gCurrentTask->td_ReturnLimit);
\r
312 SD.sd_NumPrimitives = gNumPrimitives; /* Must match compiled dictionary. */
\r
314 #ifdef PF_SUPPORT_FP
\r
315 SD.sd_FloatSize = sizeof(PF_FLOAT); /* Must match compiled dictionary. */
\r
317 SD.sd_FloatSize = 0;
\r
320 SD.sd_Reserved = 0;
\r
322 /* Set bit that specifiec whether dictionary is BIG or LITTLE Endian. */
\r
324 #if defined(PF_BIG_ENDIAN_DIC)
\r
325 int eflag = SD_F_BIG_ENDIAN_DIC;
\r
326 #elif defined(PF_LITTLE_ENDIAN_DIC)
\r
329 int eflag = IsHostLittleEndian() ? 0 : SD_F_BIG_ENDIAN_DIC;
\r
331 SD.sd_Flags = eflag;
\r
336 SD.sd_EntryPoint = EntryPoint; /* Turnkey! */
\r
340 SD.sd_EntryPoint = 0;
\r
343 /* Do we save names? */
\r
344 if( NameSize == 0 )
\r
346 SD.sd_RelContext = 0;
\r
347 SD.sd_RelHeaderPtr = 0;
\r
348 SD.sd_NameSize = 0;
\r
352 /* Development mode. */
\r
353 SD.sd_RelContext = ABS_TO_NAMEREL(gVarContext);
\r
354 rhp = ABS_TO_NAMEREL(gCurrentDictionary->dic_HeaderPtr.Byte);
\r
355 SD.sd_RelHeaderPtr = rhp;
\r
357 /* How much real name space is there? */
\r
358 NameChunkSize = QUADUP(rhp); /* Align */
\r
360 /* NameSize must be 0 or greater than NameChunkSize + 1K */
\r
361 NameSize = QUADUP(NameSize); /* Align */
\r
364 NameSize = MAX( NameSize, (NameChunkSize + 1024) );
\r
366 SD.sd_NameSize = NameSize;
\r
369 /* How much real code is there? */
\r
370 CodeChunkSize = QUADUP(rcp);
\r
371 CodeSize = QUADUP(CodeSize); /* Align */
\r
372 CodeSize = MAX( CodeSize, (CodeChunkSize + 2048) );
\r
373 SD.sd_CodeSize = CodeSize;
\r
376 /* Convert all fields in structure from Native to BigEndian. */
\r
377 p = (uint32 *) &SD;
\r
378 for( i=0; i<((int)(sizeof(SD)/sizeof(int32))); i++ )
\r
380 WriteLongBigEndian( &p[i], p[i] );
\r
383 if( WriteChunk( fid, ID_P4DI, (char *) &SD, sizeof(DictionaryInfoChunk) ) < 0 ) goto error;
\r
385 /* Write Name Fields if NameSize non-zero ------- */
\r
388 if( WriteChunk( fid, ID_P4NM, (char *) NAME_BASE,
\r
389 NameChunkSize ) < 0 ) goto error;
\r
392 /* Write Code Fields ---------------------------- */
\r
393 if( WriteChunk( fid, ID_P4CD, (char *) CODE_BASE,
\r
394 CodeChunkSize ) < 0 ) goto error;
\r
396 FormSize = sdTellFile( fid ) - 8;
\r
397 sdSeekFile( fid, 4, PF_SEEK_SET );
\r
398 if( WriteLong( fid, FormSize ) < 0 ) goto error;
\r
400 sdCloseFile( fid );
\r
404 /* Restore initialization. */
\r
406 pfExecIfDefined("AUTO.INIT");
\r
411 sdSeekFile( fid, 0, PF_SEEK_SET );
\r
412 WriteLong( fid, ID_BADF ); /* Mark file as bad. */
\r
413 sdCloseFile( fid );
\r
415 /* Restore initialization. */
\r
417 pfExecIfDefined("AUTO.INIT");
\r
422 #endif /* !PF_NO_FILEIO and !PF_NO_SHELL */
\r
425 #ifndef PF_NO_FILEIO
\r
427 /***************************************************************/
\r
428 static int32 ReadLong( FileStream *fid, int32 *ValPtr )
\r
433 numr = sdReadFile( &temp, 1, sizeof(int32), fid );
\r
434 if( numr != sizeof(int32) ) return -1;
\r
435 *ValPtr = ReadLongBigEndian( &temp );
\r
439 /***************************************************************/
\r
440 PForthDictionary pfLoadDictionary( const char *FileName, ExecToken *EntryPointPtr )
\r
442 pfDictionary_t *dic = NULL;
\r
444 DictionaryInfoChunk *sd;
\r
452 int isDicBigEndian;
\r
454 DBUG(("pfLoadDictionary( %s )\n", FileName ));
\r
457 fid = sdOpenFile( FileName, "rb" );
\r
460 pfReportError("pfLoadDictionary", PF_ERR_OPEN_FILE);
\r
464 /* Read FORM, Size, ID */
\r
465 if (ReadLong( fid, &ChunkID ) < 0) goto read_error;
\r
466 if( ChunkID != ID_FORM )
\r
468 pfReportError("pfLoadDictionary", PF_ERR_WRONG_FILE);
\r
472 if (ReadLong( fid, &FormSize ) < 0) goto read_error;
\r
473 BytesLeft = FormSize;
\r
475 if (ReadLong( fid, &ChunkID ) < 0) goto read_error;
\r
477 if( ChunkID != ID_P4TH )
\r
479 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE);
\r
483 /* Scan and parse all chunks in file. */
\r
484 while( BytesLeft > 0 )
\r
486 if (ReadLong( fid, &ChunkID ) < 0) goto read_error;
\r
487 if (ReadLong( fid, &ChunkSize ) < 0) goto read_error;
\r
490 DBUG(("ChunkID = %4s, Size = %d\n", &ChunkID, ChunkSize ));
\r
495 sd = (DictionaryInfoChunk *) pfAllocMem( ChunkSize );
\r
496 if( sd == NULL ) goto nomem_error;
\r
498 numr = sdReadFile( sd, 1, ChunkSize, fid );
\r
499 if( numr != ChunkSize ) goto read_error;
\r
500 BytesLeft -= ChunkSize;
\r
502 /* Convert all fields in structure from BigEndian to Native. */
\r
504 for( i=0; i<((int)(sizeof(*sd)/sizeof(int32))); i++ )
\r
506 p[i] = ReadLongBigEndian( &p[i] );
\r
509 isDicBigEndian = sd->sd_Flags & SD_F_BIG_ENDIAN_DIC;
\r
513 MSG("pForth loading dictionary from file "); MSG(FileName);
\r
515 MSG_NUM_D(" File format version is ", sd->sd_Version );
\r
516 MSG_NUM_D(" Name space size = ", sd->sd_NameSize );
\r
517 MSG_NUM_D(" Code space size = ", sd->sd_CodeSize );
\r
518 MSG_NUM_D(" Entry Point = ", sd->sd_EntryPoint );
\r
519 MSG( (isDicBigEndian ? " Big Endian Dictionary" :
\r
520 " Little Endian Dictionary") );
\r
521 if( isDicBigEndian == IsHostLittleEndian() ) MSG(" !!!!");
\r
525 if( sd->sd_Version > PF_FILE_VERSION )
\r
527 pfReportError("pfLoadDictionary", PF_ERR_VERSION_FUTURE );
\r
530 if( sd->sd_Version < PF_EARLIEST_FILE_VERSION )
\r
532 pfReportError("pfLoadDictionary", PF_ERR_VERSION_PAST );
\r
535 if( sd->sd_NumPrimitives > NUM_PRIMITIVES )
\r
537 pfReportError("pfLoadDictionary", PF_ERR_NOT_SUPPORTED );
\r
541 /* Check to make sure that EndianNess of dictionary matches mode of pForth. */
\r
542 #if defined(PF_BIG_ENDIAN_DIC)
\r
543 if(isDicBigEndian == 0)
\r
544 #elif defined(PF_LITTLE_ENDIAN_DIC)
\r
545 if(isDicBigEndian == 1)
\r
547 if( isDicBigEndian == IsHostLittleEndian() )
\r
550 pfReportError("pfLoadDictionary", PF_ERR_ENDIAN_CONFLICT );
\r
554 /* Check for compatible float size. */
\r
555 #ifdef PF_SUPPORT_FP
\r
556 if( sd->sd_FloatSize != sizeof(PF_FLOAT) )
\r
558 if( sd->sd_FloatSize != 0 )
\r
561 pfReportError("pfLoadDictionary", PF_ERR_FLOAT_CONFLICT );
\r
565 dic = pfCreateDictionary( sd->sd_NameSize, sd->sd_CodeSize );
\r
566 if( dic == NULL ) goto nomem_error;
\r
567 gCurrentDictionary = dic;
\r
568 if( sd->sd_NameSize > 0 )
\r
570 gVarContext = (char *) NAMEREL_TO_ABS(sd->sd_RelContext); /* Restore context. */
\r
571 gCurrentDictionary->dic_HeaderPtr.Byte = (uint8 *)
\r
572 NAMEREL_TO_ABS(sd->sd_RelHeaderPtr);
\r
577 gCurrentDictionary->dic_HeaderPtr.Byte = NULL;
\r
579 gCurrentDictionary->dic_CodePtr.Byte = (uint8 *) CODEREL_TO_ABS(sd->sd_RelCodePtr);
\r
580 gNumPrimitives = sd->sd_NumPrimitives; /* Must match compiled dictionary. */
\r
581 /* Pass EntryPoint back to caller. */
\r
582 if( EntryPointPtr != NULL ) *EntryPointPtr = sd->sd_EntryPoint;
\r
588 pfReportError("pfLoadDictionary", PF_ERR_NO_SHELL );
\r
591 if( NAME_BASE == NULL )
\r
593 pfReportError("pfLoadDictionary", PF_ERR_NO_NAMES );
\r
596 if( gCurrentDictionary == NULL )
\r
598 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
\r
601 if( ChunkSize > NAME_SIZE )
\r
603 pfReportError("pfLoadDictionary", PF_ERR_TOO_BIG);
\r
606 numr = sdReadFile( NAME_BASE, 1, ChunkSize, fid );
\r
607 if( numr != ChunkSize ) goto read_error;
\r
608 BytesLeft -= ChunkSize;
\r
609 #endif /* PF_NO_SHELL */
\r
613 if( gCurrentDictionary == NULL )
\r
615 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
\r
618 if( ChunkSize > CODE_SIZE )
\r
620 pfReportError("pfLoadDictionary", PF_ERR_TOO_BIG);
\r
623 numr = sdReadFile( CODE_BASE, 1, ChunkSize, fid );
\r
624 if( numr != ChunkSize ) goto read_error;
\r
625 BytesLeft -= ChunkSize;
\r
629 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
\r
630 sdSeekFile( fid, ChunkSize, PF_SEEK_CUR );
\r
635 sdCloseFile( fid );
\r
637 if( NAME_BASE != NULL)
\r
640 /* Find special words in dictionary for global XTs. */
\r
641 if( (Result = FindSpecialXTs()) < 0 )
\r
643 pfReportError("pfLoadDictionary: FindSpecialXTs", Result);
\r
648 DBUG(("pfLoadDictionary: return 0x%x\n", dic));
\r
649 return (PForthDictionary) dic;
\r
652 pfReportError("pfLoadDictionary", PF_ERR_NO_MEM);
\r
653 sdCloseFile( fid );
\r
657 pfReportError("pfLoadDictionary", PF_ERR_READ_FILE);
\r
659 sdCloseFile( fid );
\r
666 PForthDictionary pfLoadDictionary( const char *FileName, ExecToken *EntryPointPtr )
\r
669 (void) EntryPointPtr;
\r
672 #endif /* !PF_NO_FILEIO */
\r
676 /***************************************************************/
\r
677 PForthDictionary pfLoadStaticDictionary( void )
\r
679 #ifdef PF_STATIC_DIC
\r
681 pfDictionary_t *dic;
\r
682 int32 NewNameSize, NewCodeSize;
\r
684 if( IF_LITTLE_ENDIAN != IsHostLittleEndian() )
\r
686 MSG( (IF_LITTLE_ENDIAN ?
\r
687 "Little Endian Dictionary on " :
\r
688 "Big Endian Dictionary on ") );
\r
689 MSG( (IsHostLittleEndian() ?
\r
690 "Little Endian CPU" :
\r
691 "Big Endian CPU") );
\r
695 /* Check to make sure that EndianNess of dictionary matches mode of pForth. */
\r
696 #if defined(PF_BIG_ENDIAN_DIC)
\r
697 if(IF_LITTLE_ENDIAN == 1)
\r
698 #elif defined(PF_LITTLE_ENDIAN_DIC)
\r
699 if(IF_LITTLE_ENDIAN == 0)
\r
700 #else /* Code is native endian! */
\r
701 if( IF_LITTLE_ENDIAN != IsHostLittleEndian() )
\r
704 pfReportError("pfLoadStaticDictionary", PF_ERR_ENDIAN_CONFLICT );
\r
709 #ifndef PF_EXTRA_HEADERS
\r
710 #define PF_EXTRA_HEADERS (20000)
\r
712 #ifndef PF_EXTRA_CODE
\r
713 #define PF_EXTRA_CODE (40000)
\r
716 /* Copy static const data to allocated dictionaries. */
\r
717 NewNameSize = sizeof(MinDicNames) + PF_EXTRA_HEADERS;
\r
718 NewCodeSize = sizeof(MinDicCode) + PF_EXTRA_CODE;
\r
720 DBUG_NUM_D( "static dic name size = ", NewNameSize );
\r
721 DBUG_NUM_D( "static dic code size = ", NewCodeSize );
\r
723 gCurrentDictionary = dic = pfCreateDictionary( NewNameSize, NewCodeSize );
\r
724 if( !dic ) goto nomem_error;
\r
726 pfCopyMemory( dic->dic_HeaderBase, MinDicNames, sizeof(MinDicNames) );
\r
727 pfCopyMemory( dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode) );
\r
728 DBUG("Static data copied to newly allocated dictionaries.\n");
\r
730 dic->dic_CodePtr.Byte = (uint8 *) CODEREL_TO_ABS(CODEPTR);
\r
731 gNumPrimitives = NUM_PRIMITIVES;
\r
733 if( NAME_BASE != NULL)
\r
735 /* Setup name space. */
\r
736 dic->dic_HeaderPtr.Byte = (uint8 *) NAMEREL_TO_ABS(HEADERPTR);
\r
737 gVarContext = (char *) NAMEREL_TO_ABS(RELCONTEXT); /* Restore context. */
\r
739 /* Find special words in dictionary for global XTs. */
\r
740 if( (Result = FindSpecialXTs()) < 0 )
\r
742 pfReportError("pfLoadStaticDictionary: FindSpecialXTs", Result);
\r
747 return (PForthDictionary) dic;
\r
753 pfReportError("pfLoadStaticDictionary", PF_ERR_NO_MEM);
\r
754 #endif /* PF_STATIC_DIC */
\r