1 /* @(#) pf_save.c 98/01/26 1.3 */
2 /***************************************************************
3 ** Save and Load Dictionary
4 ** for PForth based on 'C'
6 ** Compile file based version or static data based version
7 ** depending on PF_NO_FILEIO switch.
10 ** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom
12 ** The pForth software code is dedicated to the public domain,
13 ** and any third party may reproduce, distribute and modify
14 ** the pForth software code or any derivative works thereof
15 ** without any compensation or license. The pForth software
16 ** code is provided on an "as is" basis without any warranty
17 ** of any kind, including, without limitation, the implied
18 ** warranties of merchantability and fitness for a particular
19 ** purpose and their equivalents under the laws of any jurisdiction.
21 ****************************************************************
22 ** 940225 PLB Fixed CodePtr save, was using NAMEREL instead of CODEREL
23 ** This would only work if the relative location
24 ** of names and code was the same when saved and reloaded.
25 ** 940228 PLB Added PF_NO_FILEIO version
26 ** 961204 PLB Added PF_STATIC_DIC
27 ** 000623 PLB Cast chars as ucell_t before shifting for 16 bit systems.
28 ***************************************************************/
34 /* If no File I/O, then force static dictionary. */
46 Dictionary File Format based on IFF standard.
47 The chunk IDs, sizes, and data values are all Big Endian in conformance with the IFF standard.
48 The dictionaries may be big or little endian.
51 'P4TH' - Form Identifier
56 struct DictionaryInfoChunk
60 Name and Header portion of dictionary. (Big or Little Endian) (Optional)
64 Code portion of dictionary. (Big or Little Endian)
68 /***************************************************************/
69 /* Endian-ness tools. */
70 ucell_t ReadCellBigEndian( const uint8_t *addr )
72 ucell_t temp = (ucell_t)addr[0];
73 temp = (temp << 8) | ((ucell_t)addr[1]);
74 temp = (temp << 8) | ((ucell_t)addr[2]);
75 temp = (temp << 8) | ((ucell_t)addr[3]);
76 if( sizeof(ucell_t) == 8 )
78 temp = (temp << 8) | ((ucell_t)addr[4]);
79 temp = (temp << 8) | ((ucell_t)addr[5]);
80 temp = (temp << 8) | ((ucell_t)addr[6]);
81 temp = (temp << 8) | ((ucell_t)addr[7]);
86 /***************************************************************/
87 /* Endian-ness tools. */
88 uint32_t Read32BigEndian( const uint8_t *addr )
90 uint32_t temp = (uint32_t)addr[0];
91 temp = (temp << 8) | ((uint32_t)addr[1]);
92 temp = (temp << 8) | ((uint32_t)addr[2]);
93 temp = (temp << 8) | ((uint32_t)addr[3]);
97 /***************************************************************/
98 uint16_t Read16BigEndian( const uint8_t *addr )
100 return (uint16_t) ((addr[0]<<8) | addr[1]);
103 /***************************************************************/
104 ucell_t ReadCellLittleEndian( const uint8_t *addr )
107 if( sizeof(ucell_t) == 8 )
109 temp = (temp << 8) | ((uint32_t)addr[7]);
110 temp = (temp << 8) | ((uint32_t)addr[6]);
111 temp = (temp << 8) | ((uint32_t)addr[5]);
112 temp = (temp << 8) | ((uint32_t)addr[4]);
114 temp = (temp << 8) | ((uint32_t)addr[3]);
115 temp = (temp << 8) | ((uint32_t)addr[2]);
116 temp = (temp << 8) | ((uint32_t)addr[1]);
117 temp = (temp << 8) | ((uint32_t)addr[0]);
121 /***************************************************************/
122 uint32_t Read32LittleEndian( const uint8_t *addr )
124 uint32_t temp = (uint32_t)addr[3];
125 temp = (temp << 8) | ((uint32_t)addr[2]);
126 temp = (temp << 8) | ((uint32_t)addr[1]);
127 temp = (temp << 8) | ((uint32_t)addr[0]);
131 /***************************************************************/
132 uint16_t Read16LittleEndian( const uint8_t *addr )
134 const unsigned char *bp = (const unsigned char *) addr;
135 return (uint16_t) ((bp[1]<<8) | bp[0]);
140 /***************************************************************/
141 static void ReverseCopyFloat( const PF_FLOAT *src, PF_FLOAT *dst );
143 static void ReverseCopyFloat( const PF_FLOAT *src, PF_FLOAT *dst )
146 unsigned char *d = (unsigned char *) dst;
147 const unsigned char *s = (const unsigned char *) src;
149 for( i=0; i<sizeof(PF_FLOAT); i++ )
151 d[i] = s[sizeof(PF_FLOAT) - 1 - i];
155 /***************************************************************/
156 void WriteFloatBigEndian( PF_FLOAT *addr, PF_FLOAT data )
158 if( IsHostLittleEndian() )
160 ReverseCopyFloat( &data, addr );
168 /***************************************************************/
169 PF_FLOAT ReadFloatBigEndian( const PF_FLOAT *addr )
172 if( IsHostLittleEndian() )
174 ReverseCopyFloat( addr, &data );
183 /***************************************************************/
184 void WriteFloatLittleEndian( PF_FLOAT *addr, PF_FLOAT data )
186 if( IsHostLittleEndian() )
192 ReverseCopyFloat( &data, addr );
196 /***************************************************************/
197 PF_FLOAT ReadFloatLittleEndian( const PF_FLOAT *addr )
200 if( IsHostLittleEndian() )
206 ReverseCopyFloat( addr, &data );
211 #endif /* PF_SUPPORT_FP */
213 /***************************************************************/
214 void WriteCellBigEndian( uint8_t *addr, ucell_t data )
216 /* Write should be in order of increasing address
217 * to optimize for burst writes to DRAM. */
218 if( sizeof(ucell_t) == 8 )
220 *addr++ = (uint8_t) (data>>56);
221 *addr++ = (uint8_t) (data>>48);
222 *addr++ = (uint8_t) (data>>40);
223 *addr++ = (uint8_t) (data>>32);
225 *addr++ = (uint8_t) (data>>24);
226 *addr++ = (uint8_t) (data>>16);
227 *addr++ = (uint8_t) (data>>8);
228 *addr = (uint8_t) (data);
231 /***************************************************************/
232 void Write32BigEndian( uint8_t *addr, uint32_t data )
234 *addr++ = (uint8_t) (data>>24);
235 *addr++ = (uint8_t) (data>>16);
236 *addr++ = (uint8_t) (data>>8);
237 *addr = (uint8_t) (data);
240 /***************************************************************/
241 void Write16BigEndian( uint8_t *addr, uint16_t data )
243 *addr++ = (uint8_t) (data>>8);
244 *addr = (uint8_t) (data);
247 /***************************************************************/
248 void WriteCellLittleEndian( uint8_t *addr, ucell_t data )
250 /* Write should be in order of increasing address
251 * to optimize for burst writes to DRAM. */
252 if( sizeof(ucell_t) == 8 )
254 *addr++ = (uint8_t) data; /* LSB at near end */
256 *addr++ = (uint8_t) data;
258 *addr++ = (uint8_t) data;
260 *addr++ = (uint8_t) data;
263 *addr++ = (uint8_t) data;
265 *addr++ = (uint8_t) data;
267 *addr++ = (uint8_t) data;
269 *addr = (uint8_t) data;
271 /***************************************************************/
272 void Write32LittleEndian( uint8_t *addr, uint32_t data )
274 *addr++ = (uint8_t) data;
276 *addr++ = (uint8_t) data;
278 *addr++ = (uint8_t) data;
280 *addr = (uint8_t) data;
283 /***************************************************************/
284 void Write16LittleEndian( uint8_t *addr, uint16_t data )
286 *addr++ = (uint8_t) data;
288 *addr = (uint8_t) data;
291 /***************************************************************/
292 /* Return 1 if host CPU is Little Endian */
293 int IsHostLittleEndian( void )
295 static int gEndianCheck = 1;
296 unsigned char *bp = (unsigned char *) &gEndianCheck;
297 return (int) (*bp); /* Return byte pointed to by address. If LSB then == 1 */
300 #if defined(PF_NO_FILEIO) || defined(PF_NO_SHELL)
302 cell_t ffSaveForth( const char *FileName, ExecToken EntryPoint, cell_t NameSize, cell_t CodeSize)
309 pfReportError("ffSaveForth", PF_ERR_NOT_SUPPORTED);
313 #else /* PF_NO_FILEIO or PF_NO_SHELL */
315 /***************************************************************/
316 static int Write32ToFile( FileStream *fid, uint32_t Val )
321 Write32BigEndian(pad,Val);
322 numw = sdWriteFile( pad, 1, sizeof(pad), fid );
323 if( numw != sizeof(pad) ) return -1;
327 /***************************************************************/
328 static cell_t WriteChunkToFile( FileStream *fid, cell_t ID, char *Data, int32_t NumBytes )
333 EvenNumW = EVENUP(NumBytes);
335 assert(ID <= UINT32_MAX);
336 if( Write32ToFile( fid, (uint32_t)ID ) < 0 ) goto error;
337 assert(EvenNumW <= UINT32_MAX);
338 if( Write32ToFile( fid, (uint32_t)EvenNumW ) < 0 ) goto error;
340 numw = sdWriteFile( Data, 1, EvenNumW, fid );
341 if( numw != EvenNumW ) goto error;
344 pfReportError("WriteChunkToFile", PF_ERR_WRITE_FILE);
348 /* Convert dictionary info chunk between native and on-disk (big-endian). */
350 convertDictionaryInfoWrite (DictionaryInfoChunk *sd)
352 /* Convert all fields in DictionaryInfoChunk from Native to BigEndian.
353 * This assumes they are all 32-bit integers.
356 uint32_t *p = (uint32_t *) sd;
357 for (i=0; i<((int)(sizeof(*sd)/sizeof(uint32_t))); i++)
359 Write32BigEndian( (uint8_t *)&p[i], p[i] );
364 convertDictionaryInfoRead (DictionaryInfoChunk *sd)
366 /* Convert all fields in structure from BigEndian to Native. */
368 uint32_t *p = (uint32_t *) sd;
369 for (i=0; i<((int)(sizeof(*sd)/sizeof(uint32_t))); i++)
371 p[i] = Read32BigEndian( (uint8_t *)&p[i] );
375 /****************************************************************
376 ** Save Dictionary in File.
377 ** If EntryPoint is NULL, save as development environment.
378 ** If EntryPoint is non-NULL, save as turnKey environment with no names.
380 cell_t ffSaveForth( const char *FileName, ExecToken EntryPoint, cell_t NameSize, cell_t CodeSize)
383 DictionaryInfoChunk SD;
385 uint32_t NameChunkSize = 0;
386 uint32_t CodeChunkSize;
387 uint32_t relativeCodePtr;
389 fid = sdOpenFile( FileName, "wb" );
392 pfReportError("pfSaveDictionary", PF_ERR_OPEN_FILE);
396 /* Save in uninitialized form. */
397 pfExecIfDefined("AUTO.TERM");
399 /* Write FORM Header ---------------------------- */
400 if( Write32ToFile( fid, ID_FORM ) < 0 ) goto error;
401 if( Write32ToFile( fid, 0 ) < 0 ) goto error;
402 if( Write32ToFile( fid, ID_P4TH ) < 0 ) goto error;
404 /* Write P4DI Dictionary Info ------------------ */
405 SD.sd_Version = PF_FILE_VERSION;
407 relativeCodePtr = ABS_TO_CODEREL(gCurrentDictionary->dic_CodePtr.Byte); /* 940225 */
408 SD.sd_RelCodePtr = relativeCodePtr;
409 SD.sd_UserStackSize = sizeof(cell_t) * (gCurrentTask->td_StackBase - gCurrentTask->td_StackLimit);
410 SD.sd_ReturnStackSize = sizeof(cell_t) * (gCurrentTask->td_ReturnBase - gCurrentTask->td_ReturnLimit);
411 SD.sd_NumPrimitives = gNumPrimitives; /* Must match compiled dictionary. */
414 SD.sd_FloatSize = sizeof(PF_FLOAT); /* Must match compiled dictionary. */
419 SD.sd_CellSize = sizeof(cell_t);
421 /* Set bit that specifies whether dictionary is BIG or LITTLE Endian. */
423 #if defined(PF_BIG_ENDIAN_DIC)
424 int eflag = SD_F_BIG_ENDIAN_DIC;
425 #elif defined(PF_LITTLE_ENDIAN_DIC)
428 int eflag = IsHostLittleEndian() ? 0 : SD_F_BIG_ENDIAN_DIC;
435 SD.sd_EntryPoint = EntryPoint; /* Turnkey! */
439 SD.sd_EntryPoint = 0;
442 /* Do we save names? */
445 SD.sd_RelContext = 0;
446 SD.sd_RelHeaderPtr = 0;
451 uint32_t relativeHeaderPtr;
452 /* Development mode. */
453 SD.sd_RelContext = ABS_TO_NAMEREL(gVarContext);
454 relativeHeaderPtr = ABS_TO_NAMEREL(gCurrentDictionary->dic_HeaderPtr);
455 SD.sd_RelHeaderPtr = relativeHeaderPtr;
457 /* How much real name space is there? */
458 NameChunkSize = QUADUP(relativeHeaderPtr); /* Align */
460 /* NameSize must be 0 or greater than NameChunkSize + 1K */
461 NameSize = QUADUP(NameSize); /* Align */
464 NameSize = MAX( (ucell_t)NameSize, (NameChunkSize + 1024) );
466 SD.sd_NameSize = NameSize;
469 /* How much real code is there? */
470 CodeChunkSize = QUADUP(relativeCodePtr);
471 CodeSize = QUADUP(CodeSize); /* Align */
472 CodeSize = MAX( (ucell_t)CodeSize, (CodeChunkSize + 2048) );
473 SD.sd_CodeSize = CodeSize;
476 convertDictionaryInfoWrite (&SD);
478 if( WriteChunkToFile( fid, ID_P4DI, (char *) &SD, sizeof(DictionaryInfoChunk) ) < 0 ) goto error;
480 /* Write Name Fields if NameSize non-zero ------- */
483 if( WriteChunkToFile( fid, ID_P4NM, (char *) NAME_BASE,
484 NameChunkSize ) < 0 ) goto error;
487 /* Write Code Fields ---------------------------- */
488 if( WriteChunkToFile( fid, ID_P4CD, (char *) CODE_BASE,
489 CodeChunkSize ) < 0 ) goto error;
491 FormSize = (uint32_t) sdTellFile( fid ) - 8;
492 sdSeekFile( fid, 4, PF_SEEK_SET );
493 if( Write32ToFile( fid, FormSize ) < 0 ) goto error;
497 /* Restore initialization. */
498 pfExecIfDefined("AUTO.INIT");
502 sdSeekFile( fid, 0, PF_SEEK_SET );
503 Write32ToFile( fid, ID_BADF ); /* Mark file as bad. */
506 /* Restore initialization. */
507 pfExecIfDefined("AUTO.INIT");
512 #endif /* !PF_NO_FILEIO and !PF_NO_SHELL */
517 /***************************************************************/
518 static int32_t Read32FromFile( FileStream *fid, uint32_t *ValPtr )
522 numr = sdReadFile( pad, 1, sizeof(pad), fid );
523 if( numr != sizeof(pad) ) return -1;
524 *ValPtr = Read32BigEndian( pad );
528 /***************************************************************/
529 PForthDictionary pfLoadDictionary( const char *FileName, ExecToken *EntryPointPtr )
531 pfDictionary_t *dic = NULL;
533 DictionaryInfoChunk *sd;
541 DBUG(("pfLoadDictionary( %s )\n", FileName ));
544 fid = sdOpenFile( FileName, "rb" );
547 pfReportError("pfLoadDictionary", PF_ERR_OPEN_FILE);
551 /* Read FORM, Size, ID */
552 if (Read32FromFile( fid, &ChunkID ) < 0) goto read_error;
553 if( ChunkID != ID_FORM )
555 pfReportError("pfLoadDictionary", PF_ERR_WRONG_FILE);
559 if (Read32FromFile( fid, &FormSize ) < 0) goto read_error;
560 BytesLeft = FormSize;
562 if (Read32FromFile( fid, &ChunkID ) < 0) goto read_error;
564 if( ChunkID != ID_P4TH )
566 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE);
570 /* Scan and parse all chunks in file. */
571 while( BytesLeft > 0 )
573 if (Read32FromFile( fid, &ChunkID ) < 0) goto read_error;
574 if (Read32FromFile( fid, &ChunkSize ) < 0) goto read_error;
577 DBUG(("ChunkID = %4s, Size = %d\n", (char *)&ChunkID, ChunkSize ));
582 sd = (DictionaryInfoChunk *) pfAllocMem( ChunkSize );
583 if( sd == NULL ) goto nomem_error;
585 numr = sdReadFile( sd, 1, ChunkSize, fid );
586 if( numr != ChunkSize ) goto read_error;
587 BytesLeft -= ChunkSize;
589 convertDictionaryInfoRead (sd);
591 isDicBigEndian = sd->sd_Flags & SD_F_BIG_ENDIAN_DIC;
595 MSG("pForth loading dictionary from file "); MSG(FileName);
597 MSG_NUM_D(" File format version is ", sd->sd_Version );
598 MSG_NUM_D(" Name space size = ", sd->sd_NameSize );
599 MSG_NUM_D(" Code space size = ", sd->sd_CodeSize );
600 MSG_NUM_D(" Entry Point = ", sd->sd_EntryPoint );
601 MSG_NUM_D(" Cell Size = ", sd->sd_CellSize );
602 MSG( (isDicBigEndian ? " Big Endian Dictionary" :
603 " Little Endian Dictionary") );
604 if( isDicBigEndian == IsHostLittleEndian() ) MSG(" !!!!");
608 if( sd->sd_Version > PF_FILE_VERSION )
610 pfReportError("pfLoadDictionary", PF_ERR_VERSION_FUTURE );
613 if( sd->sd_Version < PF_EARLIEST_FILE_VERSION )
615 pfReportError("pfLoadDictionary", PF_ERR_VERSION_PAST );
618 if( sd->sd_CellSize != sizeof(cell_t) )
620 pfReportError("pfLoadDictionary", PF_ERR_CELL_SIZE_CONFLICT );
623 if( sd->sd_NumPrimitives > NUM_PRIMITIVES )
625 pfReportError("pfLoadDictionary", PF_ERR_NOT_SUPPORTED );
629 /* Check to make sure that EndianNess of dictionary matches mode of pForth. */
630 #if defined(PF_BIG_ENDIAN_DIC)
631 if(isDicBigEndian == 0)
632 #elif defined(PF_LITTLE_ENDIAN_DIC)
633 if(isDicBigEndian == 1)
635 if( isDicBigEndian == IsHostLittleEndian() )
638 pfReportError("pfLoadDictionary", PF_ERR_ENDIAN_CONFLICT );
642 /* Check for compatible float size. */
644 if( sd->sd_FloatSize != sizeof(PF_FLOAT) )
646 if( sd->sd_FloatSize != 0 )
649 pfReportError("pfLoadDictionary", PF_ERR_FLOAT_CONFLICT );
653 dic = pfCreateDictionary( sd->sd_NameSize, sd->sd_CodeSize );
654 if( dic == NULL ) goto nomem_error;
655 gCurrentDictionary = dic;
656 if( sd->sd_NameSize > 0 )
658 gVarContext = NAMEREL_TO_ABS(sd->sd_RelContext); /* Restore context. */
659 gCurrentDictionary->dic_HeaderPtr = (ucell_t)(uint8_t *)
660 NAMEREL_TO_ABS(sd->sd_RelHeaderPtr);
665 gCurrentDictionary->dic_HeaderPtr = (ucell_t)NULL;
667 gCurrentDictionary->dic_CodePtr.Byte = (uint8_t *) CODEREL_TO_ABS(sd->sd_RelCodePtr);
668 gNumPrimitives = sd->sd_NumPrimitives; /* Must match compiled dictionary. */
669 /* Pass EntryPoint back to caller. */
670 if( EntryPointPtr != NULL ) *EntryPointPtr = sd->sd_EntryPoint;
676 pfReportError("pfLoadDictionary", PF_ERR_NO_SHELL );
681 pfReportError("pfLoadDictionary", PF_ERR_NO_NAMES );
684 if( gCurrentDictionary == NULL )
686 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
689 if( ChunkSize > NAME_SIZE )
691 pfReportError("pfLoadDictionary", PF_ERR_TOO_BIG);
694 numr = sdReadFile( (char *) NAME_BASE, 1, ChunkSize, fid );
695 if( numr != ChunkSize ) goto read_error;
696 BytesLeft -= ChunkSize;
697 #endif /* PF_NO_SHELL */
701 if( gCurrentDictionary == NULL )
703 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
706 if( ChunkSize > CODE_SIZE )
708 pfReportError("pfLoadDictionary", PF_ERR_TOO_BIG);
711 numr = sdReadFile( (uint8_t *) CODE_BASE, 1, ChunkSize, fid );
712 if( numr != ChunkSize ) goto read_error;
713 BytesLeft -= ChunkSize;
717 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
718 sdSeekFile( fid, ChunkSize, PF_SEEK_CUR );
728 /* Find special words in dictionary for global XTs. */
729 if( (Result = FindSpecialXTs()) < 0 )
731 pfReportError("pfLoadDictionary: FindSpecialXTs", (Err)Result);
736 DBUG(("pfLoadDictionary: return %p\n", dic));
737 return (PForthDictionary) dic;
740 pfReportError("pfLoadDictionary", PF_ERR_NO_MEM);
745 pfReportError("pfLoadDictionary", PF_ERR_READ_FILE);
754 PForthDictionary pfLoadDictionary( const char *FileName, ExecToken *EntryPointPtr )
757 (void) EntryPointPtr;
760 #endif /* !PF_NO_FILEIO */
764 /***************************************************************/
765 PForthDictionary pfLoadStaticDictionary( void )
770 cell_t NewNameSize, NewCodeSize;
772 if( IF_LITTLE_ENDIAN != IsHostLittleEndian() )
774 MSG( (IF_LITTLE_ENDIAN ?
775 "Little Endian Dictionary on " :
776 "Big Endian Dictionary on ") );
777 MSG( (IsHostLittleEndian() ?
778 "Little Endian CPU" :
783 /* Check to make sure that EndianNess of dictionary matches mode of pForth. */
784 #if defined(PF_BIG_ENDIAN_DIC)
785 if(IF_LITTLE_ENDIAN == 1)
786 #elif defined(PF_LITTLE_ENDIAN_DIC)
787 if(IF_LITTLE_ENDIAN == 0)
788 #else /* Code is native endian! */
789 if( IF_LITTLE_ENDIAN != IsHostLittleEndian() )
792 pfReportError("pfLoadStaticDictionary", PF_ERR_ENDIAN_CONFLICT );
797 #ifndef PF_EXTRA_HEADERS
798 #define PF_EXTRA_HEADERS (20000)
800 #ifndef PF_EXTRA_CODE
801 #define PF_EXTRA_CODE (40000)
804 /* Copy static const data to allocated dictionaries. */
805 NewNameSize = sizeof(MinDicNames) + PF_EXTRA_HEADERS;
806 NewCodeSize = sizeof(MinDicCode) + PF_EXTRA_CODE;
808 DBUG_NUM_D( "static dic name size = ", NewNameSize );
809 DBUG_NUM_D( "static dic code size = ", NewCodeSize );
811 gCurrentDictionary = dic = pfCreateDictionary( NewNameSize, NewCodeSize );
812 if( !dic ) goto nomem_error;
814 pfCopyMemory( (uint8_t *) dic->dic_HeaderBase, MinDicNames, sizeof(MinDicNames) );
815 pfCopyMemory( (uint8_t *) dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode) );
816 DBUG(("Static data copied to newly allocated dictionaries.\n"));
818 dic->dic_CodePtr.Byte = (uint8_t *) CODEREL_TO_ABS(CODEPTR);
819 gNumPrimitives = NUM_PRIMITIVES;
823 /* Setup name space. */
824 dic->dic_HeaderPtr = (ucell_t)(uint8_t *) NAMEREL_TO_ABS(HEADERPTR);
825 gVarContext = NAMEREL_TO_ABS(RELCONTEXT); /* Restore context. */
827 /* Find special words in dictionary for global XTs. */
828 if( (Result = FindSpecialXTs()) < 0 )
830 pfReportError("pfLoadStaticDictionary: FindSpecialXTs", Result);
835 return (PForthDictionary) dic;
841 pfReportError("pfLoadStaticDictionary", PF_ERR_NO_MEM);
842 #endif /* PF_STATIC_DIC */