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