Implement ENVIRONMENT?
[pforth] / csrc / pf_save.c
CommitLineData
8e9db35f
PB
1/* @(#) pf_save.c 98/01/26 1.3 */
2/***************************************************************
3** Save and Load Dictionary
4** for PForth based on 'C'
5**
6** Compile file based version or static data based version
7** depending on PF_NO_FILEIO switch.
8**
9** Author: Phil Burk
10** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom
11**
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.
20**
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***************************************************************/
29
30#include <assert.h>
31
32#include "pf_all.h"
33
34/* If no File I/O, then force static dictionary. */
35#ifdef PF_NO_FILEIO
36 #ifndef PF_STATIC_DIC
37 #define PF_STATIC_DIC
38 #endif
39#endif
40
41#ifdef PF_STATIC_DIC
42 #include "pfdicdat.h"
43#endif
44
45/*
46Dictionary File Format based on IFF standard.
47The chunk IDs, sizes, and data values are all Big Endian in conformance with the IFF standard.
48The dictionaries may be big or little endian.
49 'FORM'
50 size
51 'P4TH' - Form Identifier
52
53Chunks
54 'P4DI'
55 size
56 struct DictionaryInfoChunk
57
58 'P4NM'
59 size
60 Name and Header portion of dictionary. (Big or Little Endian) (Optional)
61
62 'P4CD'
63 size
64 Code portion of dictionary. (Big or Little Endian)
65*/
66
67
68/***************************************************************/
69/* Endian-ness tools. */
70ucell_t ReadCellBigEndian( const uint8_t *addr )
71{
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 )
77 {
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]);
82 }
83
84 return temp;
85}
86/***************************************************************/
87/* Endian-ness tools. */
88uint32_t Read32BigEndian( const uint8_t *addr )
89{
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]);
94 return temp;
95}
96
97/***************************************************************/
98uint16_t Read16BigEndian( const uint8_t *addr )
99{
100 return (uint16_t) ((addr[0]<<8) | addr[1]);
101}
102
103/***************************************************************/
104ucell_t ReadCellLittleEndian( const uint8_t *addr )
105{
106 ucell_t temp = 0;
107 if( sizeof(ucell_t) == 8 )
108 {
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]);
113 }
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]);
118 return temp;
119}
120
121/***************************************************************/
122uint32_t Read32LittleEndian( const uint8_t *addr )
123{
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]);
128 return temp;
129}
130
131/***************************************************************/
132uint16_t Read16LittleEndian( const uint8_t *addr )
133{
134 const unsigned char *bp = (const unsigned char *) addr;
135 return (uint16_t) ((bp[1]<<8) | bp[0]);
136}
137
138#ifdef PF_SUPPORT_FP
139
140/***************************************************************/
141static void ReverseCopyFloat( const PF_FLOAT *src, PF_FLOAT *dst );
142
143static void ReverseCopyFloat( const PF_FLOAT *src, PF_FLOAT *dst )
144{
145 int i;
146 unsigned char *d = (unsigned char *) dst;
147 const unsigned char *s = (const unsigned char *) src;
148
149 for( i=0; i<sizeof(PF_FLOAT); i++ )
150 {
151 d[i] = s[sizeof(PF_FLOAT) - 1 - i];
152 }
153}
154
155/***************************************************************/
156void WriteFloatBigEndian( PF_FLOAT *addr, PF_FLOAT data )
157{
158 if( IsHostLittleEndian() )
159 {
160 ReverseCopyFloat( &data, addr );
161 }
162 else
163 {
164 *addr = data;
165 }
166}
167
168/***************************************************************/
169PF_FLOAT ReadFloatBigEndian( const PF_FLOAT *addr )
170{
171 PF_FLOAT data;
172 if( IsHostLittleEndian() )
173 {
174 ReverseCopyFloat( addr, &data );
175 return data;
176 }
177 else
178 {
179 return *addr;
180 }
181}
182
183/***************************************************************/
184void WriteFloatLittleEndian( PF_FLOAT *addr, PF_FLOAT data )
185{
186 if( IsHostLittleEndian() )
187 {
188 *addr = data;
189 }
190 else
191 {
192 ReverseCopyFloat( &data, addr );
193 }
194}
195
196/***************************************************************/
197PF_FLOAT ReadFloatLittleEndian( const PF_FLOAT *addr )
198{
199 PF_FLOAT data;
200 if( IsHostLittleEndian() )
201 {
202 return *addr;
203 }
204 else
205 {
206 ReverseCopyFloat( addr, &data );
207 return data;
208 }
209}
210
211#endif /* PF_SUPPORT_FP */
212
213/***************************************************************/
214void WriteCellBigEndian( uint8_t *addr, ucell_t data )
215{
216 /* Write should be in order of increasing address
217 * to optimize for burst writes to DRAM. */
218 if( sizeof(ucell_t) == 8 )
219 {
220 *addr++ = (uint8_t) (data>>56);
221 *addr++ = (uint8_t) (data>>48);
222 *addr++ = (uint8_t) (data>>40);
223 *addr++ = (uint8_t) (data>>32);
224 }
225 *addr++ = (uint8_t) (data>>24);
226 *addr++ = (uint8_t) (data>>16);
227 *addr++ = (uint8_t) (data>>8);
228 *addr = (uint8_t) (data);
229}
230
231/***************************************************************/
232void Write32BigEndian( uint8_t *addr, uint32_t data )
233{
234 *addr++ = (uint8_t) (data>>24);
235 *addr++ = (uint8_t) (data>>16);
236 *addr++ = (uint8_t) (data>>8);
237 *addr = (uint8_t) (data);
238}
239
240/***************************************************************/
241void Write16BigEndian( uint8_t *addr, uint16_t data )
242{
243 *addr++ = (uint8_t) (data>>8);
244 *addr = (uint8_t) (data);
245}
246
247/***************************************************************/
248void WriteCellLittleEndian( uint8_t *addr, ucell_t data )
249{
250 /* Write should be in order of increasing address
251 * to optimize for burst writes to DRAM. */
252 if( sizeof(ucell_t) == 8 )
253 {
254 *addr++ = (uint8_t) data; /* LSB at near end */
255 data = data >> 8;
256 *addr++ = (uint8_t) data;
257 data = data >> 8;
258 *addr++ = (uint8_t) data;
259 data = data >> 8;
260 *addr++ = (uint8_t) data;
261 data = data >> 8;
262 }
263 *addr++ = (uint8_t) data;
264 data = data >> 8;
265 *addr++ = (uint8_t) data;
266 data = data >> 8;
267 *addr++ = (uint8_t) data;
268 data = data >> 8;
269 *addr = (uint8_t) data;
270}
271/***************************************************************/
272void Write32LittleEndian( uint8_t *addr, uint32_t data )
273{
274 *addr++ = (uint8_t) data;
275 data = data >> 8;
276 *addr++ = (uint8_t) data;
277 data = data >> 8;
278 *addr++ = (uint8_t) data;
279 data = data >> 8;
280 *addr = (uint8_t) data;
281}
282
283/***************************************************************/
284void Write16LittleEndian( uint8_t *addr, uint16_t data )
285{
286 *addr++ = (uint8_t) data;
287 data = data >> 8;
288 *addr = (uint8_t) data;
289}
290
291/***************************************************************/
292/* Return 1 if host CPU is Little Endian */
293int IsHostLittleEndian( void )
294{
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 */
298}
299
300#if defined(PF_NO_FILEIO) || defined(PF_NO_SHELL)
301
302cell_t ffSaveForth( const char *FileName, ExecToken EntryPoint, cell_t NameSize, cell_t CodeSize)
303{
304 TOUCH(FileName);
305 TOUCH(EntryPoint);
306 TOUCH(NameSize);
307 TOUCH(CodeSize);
308
309 pfReportError("ffSaveForth", PF_ERR_NOT_SUPPORTED);
310 return -1;
311}
312
313#else /* PF_NO_FILEIO or PF_NO_SHELL */
314
315/***************************************************************/
316static int Write32ToFile( FileStream *fid, uint32_t Val )
317{
318 int numw;
319 uint8_t pad[4];
320
321 Write32BigEndian(pad,Val);
322 numw = sdWriteFile( pad, 1, sizeof(pad), fid );
323 if( numw != sizeof(pad) ) return -1;
324 return 0;
325}
326
327/***************************************************************/
328static cell_t WriteChunkToFile( FileStream *fid, cell_t ID, char *Data, int32_t NumBytes )
329{
330 cell_t numw;
331 cell_t EvenNumW;
332
333 EvenNumW = EVENUP(NumBytes);
334
335 if( Write32ToFile( fid, ID ) < 0 ) goto error;
336 if( Write32ToFile( fid, EvenNumW ) < 0 ) goto error;
337
338 numw = sdWriteFile( Data, 1, EvenNumW, fid );
339 if( numw != EvenNumW ) goto error;
340 return 0;
341error:
342 pfReportError("WriteChunkToFile", PF_ERR_WRITE_FILE);
343 return -1;
344}
345
346/* Convert dictionary info chunk between native and on-disk (big-endian). */
347static void
348convertDictionaryInfoWrite (DictionaryInfoChunk *sd)
349{
350/* Convert all fields in DictionaryInfoChunk from Native to BigEndian.
351 * This assumes they are all 32-bit integers.
352 */
353 int i;
354 uint32_t *p = (uint32_t *) sd;
355 for (i=0; i<((int)(sizeof(*sd)/sizeof(uint32_t))); i++)
356 {
357 Write32BigEndian( (uint8_t *)&p[i], p[i] );
358 }
359}
360
361static void
362convertDictionaryInfoRead (DictionaryInfoChunk *sd)
363{
364/* Convert all fields in structure from BigEndian to Native. */
365 int i;
366 uint32_t *p = (uint32_t *) sd;
367 for (i=0; i<((int)(sizeof(*sd)/sizeof(uint32_t))); i++)
368 {
369 p[i] = Read32BigEndian( (uint8_t *)&p[i] );
370 }
371}
372
373/****************************************************************
374** Save Dictionary in File.
375** If EntryPoint is NULL, save as development environment.
376** If EntryPoint is non-NULL, save as turnKey environment with no names.
377*/
378cell_t ffSaveForth( const char *FileName, ExecToken EntryPoint, cell_t NameSize, cell_t CodeSize)
379{
380 FileStream *fid;
381 DictionaryInfoChunk SD;
382 uint32_t FormSize;
383 uint32_t NameChunkSize = 0;
384 uint32_t CodeChunkSize;
385 uint32_t relativeCodePtr;
386
387 fid = sdOpenFile( FileName, "wb" );
388 if( fid == NULL )
389 {
390 pfReportError("pfSaveDictionary", PF_ERR_OPEN_FILE);
391 return -1;
392 }
393
394/* Save in uninitialized form. */
395 pfExecIfDefined("AUTO.TERM");
396
397/* Write FORM Header ---------------------------- */
398 if( Write32ToFile( fid, ID_FORM ) < 0 ) goto error;
399 if( Write32ToFile( fid, 0 ) < 0 ) goto error;
400 if( Write32ToFile( fid, ID_P4TH ) < 0 ) goto error;
401
402/* Write P4DI Dictionary Info ------------------ */
403 SD.sd_Version = PF_FILE_VERSION;
404
405 relativeCodePtr = ABS_TO_CODEREL(gCurrentDictionary->dic_CodePtr.Byte); /* 940225 */
406 SD.sd_RelCodePtr = relativeCodePtr;
407 SD.sd_UserStackSize = sizeof(cell_t) * (gCurrentTask->td_StackBase - gCurrentTask->td_StackLimit);
408 SD.sd_ReturnStackSize = sizeof(cell_t) * (gCurrentTask->td_ReturnBase - gCurrentTask->td_ReturnLimit);
409 SD.sd_NumPrimitives = gNumPrimitives; /* Must match compiled dictionary. */
410
411#ifdef PF_SUPPORT_FP
412 SD.sd_FloatSize = sizeof(PF_FLOAT); /* Must match compiled dictionary. */
413#else
414 SD.sd_FloatSize = 0;
415#endif
416
417 SD.sd_CellSize = sizeof(cell_t);
418
419/* Set bit that specifies whether dictionary is BIG or LITTLE Endian. */
420 {
421#if defined(PF_BIG_ENDIAN_DIC)
422 int eflag = SD_F_BIG_ENDIAN_DIC;
423#elif defined(PF_LITTLE_ENDIAN_DIC)
424 int eflag = 0;
425#else
426 int eflag = IsHostLittleEndian() ? 0 : SD_F_BIG_ENDIAN_DIC;
427#endif
428 SD.sd_Flags = eflag;
429 }
430
431 if( EntryPoint )
432 {
433 SD.sd_EntryPoint = EntryPoint; /* Turnkey! */
434 }
435 else
436 {
437 SD.sd_EntryPoint = 0;
438 }
439
440/* Do we save names? */
441 if( NameSize == 0 )
442 {
443 SD.sd_RelContext = 0;
444 SD.sd_RelHeaderPtr = 0;
445 SD.sd_NameSize = 0;
446 }
447 else
448 {
449 uint32_t relativeHeaderPtr;
450/* Development mode. */
451 SD.sd_RelContext = ABS_TO_NAMEREL(gVarContext);
452 relativeHeaderPtr = ABS_TO_NAMEREL(gCurrentDictionary->dic_HeaderPtr);
453 SD.sd_RelHeaderPtr = relativeHeaderPtr;
454
455/* How much real name space is there? */
456 NameChunkSize = QUADUP(relativeHeaderPtr); /* Align */
457
458/* NameSize must be 0 or greater than NameChunkSize + 1K */
459 NameSize = QUADUP(NameSize); /* Align */
460 if( NameSize > 0 )
461 {
462 NameSize = MAX( NameSize, (NameChunkSize + 1024) );
463 }
464 SD.sd_NameSize = NameSize;
465 }
466
467/* How much real code is there? */
468 CodeChunkSize = QUADUP(relativeCodePtr);
469 CodeSize = QUADUP(CodeSize); /* Align */
470 CodeSize = MAX( CodeSize, (CodeChunkSize + 2048) );
471 SD.sd_CodeSize = CodeSize;
472
473
474 convertDictionaryInfoWrite (&SD);
475
476 if( WriteChunkToFile( fid, ID_P4DI, (char *) &SD, sizeof(DictionaryInfoChunk) ) < 0 ) goto error;
477
478/* Write Name Fields if NameSize non-zero ------- */
479 if( NameSize > 0 )
480 {
481 if( WriteChunkToFile( fid, ID_P4NM, (char *) NAME_BASE,
482 NameChunkSize ) < 0 ) goto error;
483 }
484
485/* Write Code Fields ---------------------------- */
486 if( WriteChunkToFile( fid, ID_P4CD, (char *) CODE_BASE,
487 CodeChunkSize ) < 0 ) goto error;
488
3a940535 489 FormSize = (uint32_t) sdTellFile( fid ) - 8;
8e9db35f
PB
490 sdSeekFile( fid, 4, PF_SEEK_SET );
491 if( Write32ToFile( fid, FormSize ) < 0 ) goto error;
492
493 sdCloseFile( fid );
494
495/* Restore initialization. */
496 pfExecIfDefined("AUTO.INIT");
497 return 0;
498
499error:
500 sdSeekFile( fid, 0, PF_SEEK_SET );
501 Write32ToFile( fid, ID_BADF ); /* Mark file as bad. */
502 sdCloseFile( fid );
503
504/* Restore initialization. */
505 pfExecIfDefined("AUTO.INIT");
506
507 return -1;
508}
509
510#endif /* !PF_NO_FILEIO and !PF_NO_SHELL */
511
512
513#ifndef PF_NO_FILEIO
514
515/***************************************************************/
516static int32_t Read32FromFile( FileStream *fid, uint32_t *ValPtr )
517{
518 int32_t numr;
519 uint8_t pad[4];
520 numr = sdReadFile( pad, 1, sizeof(pad), fid );
521 if( numr != sizeof(pad) ) return -1;
522 *ValPtr = Read32BigEndian( pad );
523 return 0;
524}
525
526/***************************************************************/
527PForthDictionary pfLoadDictionary( const char *FileName, ExecToken *EntryPointPtr )
528{
529 pfDictionary_t *dic = NULL;
530 FileStream *fid;
531 DictionaryInfoChunk *sd;
532 uint32_t ChunkID;
533 uint32_t ChunkSize;
534 uint32_t FormSize;
535 uint32_t BytesLeft;
536 uint32_t numr;
537 int isDicBigEndian;
538
539DBUG(("pfLoadDictionary( %s )\n", FileName ));
540
541/* Open file. */
542 fid = sdOpenFile( FileName, "rb" );
543 if( fid == NULL )
544 {
545 pfReportError("pfLoadDictionary", PF_ERR_OPEN_FILE);
546 goto xt_error;
547 }
548
549/* Read FORM, Size, ID */
550 if (Read32FromFile( fid, &ChunkID ) < 0) goto read_error;
551 if( ChunkID != ID_FORM )
552 {
553 pfReportError("pfLoadDictionary", PF_ERR_WRONG_FILE);
554 goto error;
555 }
556
557 if (Read32FromFile( fid, &FormSize ) < 0) goto read_error;
558 BytesLeft = FormSize;
559
560 if (Read32FromFile( fid, &ChunkID ) < 0) goto read_error;
561 BytesLeft -= 4;
562 if( ChunkID != ID_P4TH )
563 {
564 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE);
565 goto error;
566 }
567
568/* Scan and parse all chunks in file. */
569 while( BytesLeft > 0 )
570 {
571 if (Read32FromFile( fid, &ChunkID ) < 0) goto read_error;
572 if (Read32FromFile( fid, &ChunkSize ) < 0) goto read_error;
573 BytesLeft -= 8;
574
575 DBUG(("ChunkID = %4s, Size = %d\n", (char *)&ChunkID, ChunkSize ));
576
577 switch( ChunkID )
578 {
579 case ID_P4DI:
580 sd = (DictionaryInfoChunk *) pfAllocMem( ChunkSize );
581 if( sd == NULL ) goto nomem_error;
582
583 numr = sdReadFile( sd, 1, ChunkSize, fid );
584 if( numr != ChunkSize ) goto read_error;
585 BytesLeft -= ChunkSize;
586
587 convertDictionaryInfoRead (sd);
588
589 isDicBigEndian = sd->sd_Flags & SD_F_BIG_ENDIAN_DIC;
590
591 if( !gVarQuiet )
592 {
593 MSG("pForth loading dictionary from file "); MSG(FileName);
594 EMIT_CR;
595 MSG_NUM_D(" File format version is ", sd->sd_Version );
596 MSG_NUM_D(" Name space size = ", sd->sd_NameSize );
597 MSG_NUM_D(" Code space size = ", sd->sd_CodeSize );
598 MSG_NUM_D(" Entry Point = ", sd->sd_EntryPoint );
599 MSG_NUM_D(" Cell Size = ", sd->sd_CellSize );
600 MSG( (isDicBigEndian ? " Big Endian Dictionary" :
601 " Little Endian Dictionary") );
602 if( isDicBigEndian == IsHostLittleEndian() ) MSG(" !!!!");
603 EMIT_CR;
604 }
605
606 if( sd->sd_Version > PF_FILE_VERSION )
607 {
608 pfReportError("pfLoadDictionary", PF_ERR_VERSION_FUTURE );
609 goto error;
610 }
611 if( sd->sd_Version < PF_EARLIEST_FILE_VERSION )
612 {
613 pfReportError("pfLoadDictionary", PF_ERR_VERSION_PAST );
614 goto error;
615 }
616 if( sd->sd_CellSize != sizeof(cell_t) )
617 {
618 pfReportError("pfLoadDictionary", PF_ERR_CELL_SIZE_CONFLICT );
619 goto error;
620 }
621 if( sd->sd_NumPrimitives > NUM_PRIMITIVES )
622 {
623 pfReportError("pfLoadDictionary", PF_ERR_NOT_SUPPORTED );
624 goto error;
625 }
626
627/* Check to make sure that EndianNess of dictionary matches mode of pForth. */
628#if defined(PF_BIG_ENDIAN_DIC)
629 if(isDicBigEndian == 0)
630#elif defined(PF_LITTLE_ENDIAN_DIC)
631 if(isDicBigEndian == 1)
632#else
633 if( isDicBigEndian == IsHostLittleEndian() )
634#endif
635 {
636 pfReportError("pfLoadDictionary", PF_ERR_ENDIAN_CONFLICT );
637 goto error;
638 }
639
640/* Check for compatible float size. */
641#ifdef PF_SUPPORT_FP
642 if( sd->sd_FloatSize != sizeof(PF_FLOAT) )
643#else
644 if( sd->sd_FloatSize != 0 )
645#endif
646 {
647 pfReportError("pfLoadDictionary", PF_ERR_FLOAT_CONFLICT );
648 goto error;
649 }
650
651 dic = pfCreateDictionary( sd->sd_NameSize, sd->sd_CodeSize );
652 if( dic == NULL ) goto nomem_error;
653 gCurrentDictionary = dic;
654 if( sd->sd_NameSize > 0 )
655 {
656 gVarContext = NAMEREL_TO_ABS(sd->sd_RelContext); /* Restore context. */
657 gCurrentDictionary->dic_HeaderPtr = (ucell_t)(uint8_t *)
658 NAMEREL_TO_ABS(sd->sd_RelHeaderPtr);
659 }
660 else
661 {
662 gVarContext = 0;
663 gCurrentDictionary->dic_HeaderPtr = (ucell_t)NULL;
664 }
665 gCurrentDictionary->dic_CodePtr.Byte = (uint8_t *) CODEREL_TO_ABS(sd->sd_RelCodePtr);
666 gNumPrimitives = sd->sd_NumPrimitives; /* Must match compiled dictionary. */
667/* Pass EntryPoint back to caller. */
668 if( EntryPointPtr != NULL ) *EntryPointPtr = sd->sd_EntryPoint;
669 pfFreeMem(sd);
670 break;
671
672 case ID_P4NM:
673#ifdef PF_NO_SHELL
674 pfReportError("pfLoadDictionary", PF_ERR_NO_SHELL );
675 goto error;
676#else
677 if( NAME_BASE == 0 )
678 {
679 pfReportError("pfLoadDictionary", PF_ERR_NO_NAMES );
680 goto error;
681 }
682 if( gCurrentDictionary == NULL )
683 {
684 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
685 goto error;
686 }
687 if( ChunkSize > NAME_SIZE )
688 {
689 pfReportError("pfLoadDictionary", PF_ERR_TOO_BIG);
690 goto error;
691 }
692 numr = sdReadFile( (char *) NAME_BASE, 1, ChunkSize, fid );
693 if( numr != ChunkSize ) goto read_error;
694 BytesLeft -= ChunkSize;
695#endif /* PF_NO_SHELL */
696 break;
697
698 case ID_P4CD:
699 if( gCurrentDictionary == NULL )
700 {
701 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
702 goto error;
703 }
704 if( ChunkSize > CODE_SIZE )
705 {
706 pfReportError("pfLoadDictionary", PF_ERR_TOO_BIG);
707 goto error;
708 }
709 numr = sdReadFile( (uint8_t *) CODE_BASE, 1, ChunkSize, fid );
710 if( numr != ChunkSize ) goto read_error;
711 BytesLeft -= ChunkSize;
712 break;
713
714 default:
715 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
716 sdSeekFile( fid, ChunkSize, PF_SEEK_CUR );
717 break;
718 }
719 }
720
721 sdCloseFile( fid );
722
723 if( NAME_BASE != 0)
724 {
725 cell_t Result;
726/* Find special words in dictionary for global XTs. */
727 if( (Result = FindSpecialXTs()) < 0 )
728 {
729 pfReportError("pfLoadDictionary: FindSpecialXTs", Result);
730 goto error;
731 }
732 }
733
734DBUG(("pfLoadDictionary: return %p\n", dic));
735 return (PForthDictionary) dic;
736
737nomem_error:
738 pfReportError("pfLoadDictionary", PF_ERR_NO_MEM);
739 sdCloseFile( fid );
740 return NULL;
741
742read_error:
743 pfReportError("pfLoadDictionary", PF_ERR_READ_FILE);
744error:
745 sdCloseFile( fid );
746xt_error:
747 return NULL;
748}
749
750#else
751
752PForthDictionary pfLoadDictionary( const char *FileName, ExecToken *EntryPointPtr )
753{
754 (void) FileName;
755 (void) EntryPointPtr;
756 return NULL;
757}
758#endif /* !PF_NO_FILEIO */
759
760
761
762/***************************************************************/
763PForthDictionary pfLoadStaticDictionary( void )
764{
765#ifdef PF_STATIC_DIC
766 cell_t Result;
767 pfDictionary_t *dic;
768 cell_t NewNameSize, NewCodeSize;
769
770 if( IF_LITTLE_ENDIAN != IsHostLittleEndian() )
771 {
772 MSG( (IF_LITTLE_ENDIAN ?
773 "Little Endian Dictionary on " :
774 "Big Endian Dictionary on ") );
775 MSG( (IsHostLittleEndian() ?
776 "Little Endian CPU" :
777 "Big Endian CPU") );
778 EMIT_CR;
779 }
780
781/* Check to make sure that EndianNess of dictionary matches mode of pForth. */
782#if defined(PF_BIG_ENDIAN_DIC)
783 if(IF_LITTLE_ENDIAN == 1)
784#elif defined(PF_LITTLE_ENDIAN_DIC)
785 if(IF_LITTLE_ENDIAN == 0)
786#else /* Code is native endian! */
787 if( IF_LITTLE_ENDIAN != IsHostLittleEndian() )
788#endif
789 {
790 pfReportError("pfLoadStaticDictionary", PF_ERR_ENDIAN_CONFLICT );
791 goto error;
792 }
793
794
795#ifndef PF_EXTRA_HEADERS
796 #define PF_EXTRA_HEADERS (20000)
797#endif
798#ifndef PF_EXTRA_CODE
799 #define PF_EXTRA_CODE (40000)
800#endif
801
802/* Copy static const data to allocated dictionaries. */
803 NewNameSize = sizeof(MinDicNames) + PF_EXTRA_HEADERS;
804 NewCodeSize = sizeof(MinDicCode) + PF_EXTRA_CODE;
805
806 DBUG_NUM_D( "static dic name size = ", NewNameSize );
807 DBUG_NUM_D( "static dic code size = ", NewCodeSize );
808
809 gCurrentDictionary = dic = pfCreateDictionary( NewNameSize, NewCodeSize );
810 if( !dic ) goto nomem_error;
811
812 pfCopyMemory( (uint8_t *) dic->dic_HeaderBase, MinDicNames, sizeof(MinDicNames) );
813 pfCopyMemory( (uint8_t *) dic->dic_CodeBase, MinDicCode, sizeof(MinDicCode) );
814 DBUG(("Static data copied to newly allocated dictionaries.\n"));
815
816 dic->dic_CodePtr.Byte = (uint8_t *) CODEREL_TO_ABS(CODEPTR);
817 gNumPrimitives = NUM_PRIMITIVES;
818
819 if( NAME_BASE != 0)
820 {
821/* Setup name space. */
822 dic->dic_HeaderPtr = (ucell_t)(uint8_t *) NAMEREL_TO_ABS(HEADERPTR);
823 gVarContext = NAMEREL_TO_ABS(RELCONTEXT); /* Restore context. */
824
825/* Find special words in dictionary for global XTs. */
826 if( (Result = FindSpecialXTs()) < 0 )
827 {
828 pfReportError("pfLoadStaticDictionary: FindSpecialXTs", Result);
829 goto error;
830 }
831 }
832
833 return (PForthDictionary) dic;
834
835error:
836 return NULL;
837
838nomem_error:
839 pfReportError("pfLoadStaticDictionary", PF_ERR_NO_MEM);
840#endif /* PF_STATIC_DIC */
841
842 return NULL;
843}
844