Review feedback on types
[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{
49295627 318 cell_t numw;
8e9db35f
PB
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
49295627 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;
8e9db35f
PB
339
340 numw = sdWriteFile( Data, 1, EvenNumW, fid );
341 if( numw != EvenNumW ) goto error;
342 return 0;
343error:
344 pfReportError("WriteChunkToFile", PF_ERR_WRITE_FILE);
345 return -1;
346}
347
348/* Convert dictionary info chunk between native and on-disk (big-endian). */
349static void
350convertDictionaryInfoWrite (DictionaryInfoChunk *sd)
351{
352/* Convert all fields in DictionaryInfoChunk from Native to BigEndian.
353 * This assumes they are all 32-bit integers.
354 */
355 int i;
356 uint32_t *p = (uint32_t *) sd;
357 for (i=0; i<((int)(sizeof(*sd)/sizeof(uint32_t))); i++)
358 {
359 Write32BigEndian( (uint8_t *)&p[i], p[i] );
360 }
361}
362
363static void
364convertDictionaryInfoRead (DictionaryInfoChunk *sd)
365{
366/* Convert all fields in structure from BigEndian to Native. */
367 int i;
368 uint32_t *p = (uint32_t *) sd;
369 for (i=0; i<((int)(sizeof(*sd)/sizeof(uint32_t))); i++)
370 {
371 p[i] = Read32BigEndian( (uint8_t *)&p[i] );
372 }
373}
374
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.
379*/
380cell_t ffSaveForth( const char *FileName, ExecToken EntryPoint, cell_t NameSize, cell_t CodeSize)
381{
382 FileStream *fid;
383 DictionaryInfoChunk SD;
384 uint32_t FormSize;
385 uint32_t NameChunkSize = 0;
386 uint32_t CodeChunkSize;
387 uint32_t relativeCodePtr;
388
389 fid = sdOpenFile( FileName, "wb" );
390 if( fid == NULL )
391 {
392 pfReportError("pfSaveDictionary", PF_ERR_OPEN_FILE);
393 return -1;
394 }
395
396/* Save in uninitialized form. */
397 pfExecIfDefined("AUTO.TERM");
398
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;
403
404/* Write P4DI Dictionary Info ------------------ */
405 SD.sd_Version = PF_FILE_VERSION;
406
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. */
412
413#ifdef PF_SUPPORT_FP
414 SD.sd_FloatSize = sizeof(PF_FLOAT); /* Must match compiled dictionary. */
415#else
416 SD.sd_FloatSize = 0;
417#endif
418
419 SD.sd_CellSize = sizeof(cell_t);
420
421/* Set bit that specifies whether dictionary is BIG or LITTLE Endian. */
422 {
423#if defined(PF_BIG_ENDIAN_DIC)
424 int eflag = SD_F_BIG_ENDIAN_DIC;
425#elif defined(PF_LITTLE_ENDIAN_DIC)
426 int eflag = 0;
427#else
428 int eflag = IsHostLittleEndian() ? 0 : SD_F_BIG_ENDIAN_DIC;
429#endif
430 SD.sd_Flags = eflag;
431 }
432
433 if( EntryPoint )
434 {
435 SD.sd_EntryPoint = EntryPoint; /* Turnkey! */
436 }
437 else
438 {
439 SD.sd_EntryPoint = 0;
440 }
441
442/* Do we save names? */
443 if( NameSize == 0 )
444 {
445 SD.sd_RelContext = 0;
446 SD.sd_RelHeaderPtr = 0;
447 SD.sd_NameSize = 0;
448 }
449 else
450 {
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;
456
457/* How much real name space is there? */
458 NameChunkSize = QUADUP(relativeHeaderPtr); /* Align */
459
460/* NameSize must be 0 or greater than NameChunkSize + 1K */
461 NameSize = QUADUP(NameSize); /* Align */
462 if( NameSize > 0 )
463 {
65279741 464 NameSize = MAX( (ucell_t)NameSize, (NameChunkSize + 1024) );
8e9db35f
PB
465 }
466 SD.sd_NameSize = NameSize;
467 }
468
469/* How much real code is there? */
470 CodeChunkSize = QUADUP(relativeCodePtr);
471 CodeSize = QUADUP(CodeSize); /* Align */
65279741 472 CodeSize = MAX( (ucell_t)CodeSize, (CodeChunkSize + 2048) );
8e9db35f
PB
473 SD.sd_CodeSize = CodeSize;
474
475
476 convertDictionaryInfoWrite (&SD);
477
478 if( WriteChunkToFile( fid, ID_P4DI, (char *) &SD, sizeof(DictionaryInfoChunk) ) < 0 ) goto error;
479
480/* Write Name Fields if NameSize non-zero ------- */
481 if( NameSize > 0 )
482 {
483 if( WriteChunkToFile( fid, ID_P4NM, (char *) NAME_BASE,
484 NameChunkSize ) < 0 ) goto error;
485 }
486
487/* Write Code Fields ---------------------------- */
488 if( WriteChunkToFile( fid, ID_P4CD, (char *) CODE_BASE,
489 CodeChunkSize ) < 0 ) goto error;
490
3a940535 491 FormSize = (uint32_t) sdTellFile( fid ) - 8;
8e9db35f
PB
492 sdSeekFile( fid, 4, PF_SEEK_SET );
493 if( Write32ToFile( fid, FormSize ) < 0 ) goto error;
494
495 sdCloseFile( fid );
496
497/* Restore initialization. */
498 pfExecIfDefined("AUTO.INIT");
499 return 0;
500
501error:
502 sdSeekFile( fid, 0, PF_SEEK_SET );
503 Write32ToFile( fid, ID_BADF ); /* Mark file as bad. */
504 sdCloseFile( fid );
505
506/* Restore initialization. */
507 pfExecIfDefined("AUTO.INIT");
508
509 return -1;
510}
511
512#endif /* !PF_NO_FILEIO and !PF_NO_SHELL */
513
514
515#ifndef PF_NO_FILEIO
516
517/***************************************************************/
518static int32_t Read32FromFile( FileStream *fid, uint32_t *ValPtr )
519{
49295627 520 cell_t numr;
8e9db35f
PB
521 uint8_t pad[4];
522 numr = sdReadFile( pad, 1, sizeof(pad), fid );
523 if( numr != sizeof(pad) ) return -1;
524 *ValPtr = Read32BigEndian( pad );
525 return 0;
526}
527
528/***************************************************************/
529PForthDictionary pfLoadDictionary( const char *FileName, ExecToken *EntryPointPtr )
530{
531 pfDictionary_t *dic = NULL;
532 FileStream *fid;
533 DictionaryInfoChunk *sd;
534 uint32_t ChunkID;
535 uint32_t ChunkSize;
536 uint32_t FormSize;
537 uint32_t BytesLeft;
49295627 538 cell_t numr;
8e9db35f
PB
539 int isDicBigEndian;
540
541DBUG(("pfLoadDictionary( %s )\n", FileName ));
542
543/* Open file. */
544 fid = sdOpenFile( FileName, "rb" );
545 if( fid == NULL )
546 {
547 pfReportError("pfLoadDictionary", PF_ERR_OPEN_FILE);
548 goto xt_error;
549 }
550
551/* Read FORM, Size, ID */
552 if (Read32FromFile( fid, &ChunkID ) < 0) goto read_error;
553 if( ChunkID != ID_FORM )
554 {
555 pfReportError("pfLoadDictionary", PF_ERR_WRONG_FILE);
556 goto error;
557 }
558
559 if (Read32FromFile( fid, &FormSize ) < 0) goto read_error;
560 BytesLeft = FormSize;
561
562 if (Read32FromFile( fid, &ChunkID ) < 0) goto read_error;
563 BytesLeft -= 4;
564 if( ChunkID != ID_P4TH )
565 {
566 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE);
567 goto error;
568 }
569
570/* Scan and parse all chunks in file. */
571 while( BytesLeft > 0 )
572 {
573 if (Read32FromFile( fid, &ChunkID ) < 0) goto read_error;
574 if (Read32FromFile( fid, &ChunkSize ) < 0) goto read_error;
575 BytesLeft -= 8;
576
577 DBUG(("ChunkID = %4s, Size = %d\n", (char *)&ChunkID, ChunkSize ));
578
579 switch( ChunkID )
580 {
581 case ID_P4DI:
582 sd = (DictionaryInfoChunk *) pfAllocMem( ChunkSize );
583 if( sd == NULL ) goto nomem_error;
584
585 numr = sdReadFile( sd, 1, ChunkSize, fid );
586 if( numr != ChunkSize ) goto read_error;
587 BytesLeft -= ChunkSize;
588
589 convertDictionaryInfoRead (sd);
590
591 isDicBigEndian = sd->sd_Flags & SD_F_BIG_ENDIAN_DIC;
592
593 if( !gVarQuiet )
594 {
595 MSG("pForth loading dictionary from file "); MSG(FileName);
596 EMIT_CR;
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(" !!!!");
605 EMIT_CR;
606 }
607
608 if( sd->sd_Version > PF_FILE_VERSION )
609 {
610 pfReportError("pfLoadDictionary", PF_ERR_VERSION_FUTURE );
611 goto error;
612 }
613 if( sd->sd_Version < PF_EARLIEST_FILE_VERSION )
614 {
615 pfReportError("pfLoadDictionary", PF_ERR_VERSION_PAST );
616 goto error;
617 }
618 if( sd->sd_CellSize != sizeof(cell_t) )
619 {
620 pfReportError("pfLoadDictionary", PF_ERR_CELL_SIZE_CONFLICT );
621 goto error;
622 }
623 if( sd->sd_NumPrimitives > NUM_PRIMITIVES )
624 {
625 pfReportError("pfLoadDictionary", PF_ERR_NOT_SUPPORTED );
626 goto error;
627 }
628
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)
634#else
635 if( isDicBigEndian == IsHostLittleEndian() )
636#endif
637 {
638 pfReportError("pfLoadDictionary", PF_ERR_ENDIAN_CONFLICT );
639 goto error;
640 }
641
642/* Check for compatible float size. */
643#ifdef PF_SUPPORT_FP
644 if( sd->sd_FloatSize != sizeof(PF_FLOAT) )
645#else
646 if( sd->sd_FloatSize != 0 )
647#endif
648 {
649 pfReportError("pfLoadDictionary", PF_ERR_FLOAT_CONFLICT );
650 goto error;
651 }
652
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 )
657 {
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);
661 }
662 else
663 {
664 gVarContext = 0;
665 gCurrentDictionary->dic_HeaderPtr = (ucell_t)NULL;
666 }
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;
671 pfFreeMem(sd);
672 break;
673
674 case ID_P4NM:
675#ifdef PF_NO_SHELL
676 pfReportError("pfLoadDictionary", PF_ERR_NO_SHELL );
677 goto error;
678#else
679 if( NAME_BASE == 0 )
680 {
681 pfReportError("pfLoadDictionary", PF_ERR_NO_NAMES );
682 goto error;
683 }
684 if( gCurrentDictionary == NULL )
685 {
686 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
687 goto error;
688 }
689 if( ChunkSize > NAME_SIZE )
690 {
691 pfReportError("pfLoadDictionary", PF_ERR_TOO_BIG);
692 goto error;
693 }
694 numr = sdReadFile( (char *) NAME_BASE, 1, ChunkSize, fid );
695 if( numr != ChunkSize ) goto read_error;
696 BytesLeft -= ChunkSize;
697#endif /* PF_NO_SHELL */
698 break;
699
700 case ID_P4CD:
701 if( gCurrentDictionary == NULL )
702 {
703 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
704 goto error;
705 }
706 if( ChunkSize > CODE_SIZE )
707 {
708 pfReportError("pfLoadDictionary", PF_ERR_TOO_BIG);
709 goto error;
710 }
711 numr = sdReadFile( (uint8_t *) CODE_BASE, 1, ChunkSize, fid );
712 if( numr != ChunkSize ) goto read_error;
713 BytesLeft -= ChunkSize;
714 break;
715
716 default:
717 pfReportError("pfLoadDictionary", PF_ERR_BAD_FILE );
718 sdSeekFile( fid, ChunkSize, PF_SEEK_CUR );
719 break;
720 }
721 }
722
723 sdCloseFile( fid );
724
725 if( NAME_BASE != 0)
726 {
727 cell_t Result;
728/* Find special words in dictionary for global XTs. */
729 if( (Result = FindSpecialXTs()) < 0 )
730 {
529bb4e2 731 pfReportError("pfLoadDictionary: FindSpecialXTs", (Err)Result);
8e9db35f
PB
732 goto error;
733 }
734 }
735
736DBUG(("pfLoadDictionary: return %p\n", dic));
737 return (PForthDictionary) dic;
738
739nomem_error:
740 pfReportError("pfLoadDictionary", PF_ERR_NO_MEM);
741 sdCloseFile( fid );
742 return NULL;
743
744read_error:
745 pfReportError("pfLoadDictionary", PF_ERR_READ_FILE);
746error:
747 sdCloseFile( fid );
748xt_error:
749 return NULL;
750}
751
752#else
753
754PForthDictionary pfLoadDictionary( const char *FileName, ExecToken *EntryPointPtr )
755{
756 (void) FileName;
757 (void) EntryPointPtr;
758 return NULL;
759}
760#endif /* !PF_NO_FILEIO */
761
762
763
764/***************************************************************/
765PForthDictionary pfLoadStaticDictionary( void )
766{
767#ifdef PF_STATIC_DIC
768 cell_t Result;
769 pfDictionary_t *dic;
770 cell_t NewNameSize, NewCodeSize;
771
772 if( IF_LITTLE_ENDIAN != IsHostLittleEndian() )
773 {
774 MSG( (IF_LITTLE_ENDIAN ?
775 "Little Endian Dictionary on " :
776 "Big Endian Dictionary on ") );
777 MSG( (IsHostLittleEndian() ?
778 "Little Endian CPU" :
779 "Big Endian CPU") );
780 EMIT_CR;
781 }
782
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() )
790#endif
791 {
792 pfReportError("pfLoadStaticDictionary", PF_ERR_ENDIAN_CONFLICT );
793 goto error;
794 }
795
796
797#ifndef PF_EXTRA_HEADERS
798 #define PF_EXTRA_HEADERS (20000)
799#endif
800#ifndef PF_EXTRA_CODE
801 #define PF_EXTRA_CODE (40000)
802#endif
803
804/* Copy static const data to allocated dictionaries. */
805 NewNameSize = sizeof(MinDicNames) + PF_EXTRA_HEADERS;
806 NewCodeSize = sizeof(MinDicCode) + PF_EXTRA_CODE;
807
808 DBUG_NUM_D( "static dic name size = ", NewNameSize );
809 DBUG_NUM_D( "static dic code size = ", NewCodeSize );
810
811 gCurrentDictionary = dic = pfCreateDictionary( NewNameSize, NewCodeSize );
812 if( !dic ) goto nomem_error;
813
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"));
817
818 dic->dic_CodePtr.Byte = (uint8_t *) CODEREL_TO_ABS(CODEPTR);
819 gNumPrimitives = NUM_PRIMITIVES;
820
821 if( NAME_BASE != 0)
822 {
823/* Setup name space. */
824 dic->dic_HeaderPtr = (ucell_t)(uint8_t *) NAMEREL_TO_ABS(HEADERPTR);
825 gVarContext = NAMEREL_TO_ABS(RELCONTEXT); /* Restore context. */
826
827/* Find special words in dictionary for global XTs. */
828 if( (Result = FindSpecialXTs()) < 0 )
829 {
830 pfReportError("pfLoadStaticDictionary: FindSpecialXTs", Result);
831 goto error;
832 }
833 }
834
835 return (PForthDictionary) dic;
836
837error:
838 return NULL;
839
840nomem_error:
841 pfReportError("pfLoadStaticDictionary", PF_ERR_NO_MEM);
842#endif /* PF_STATIC_DIC */
843
844 return NULL;
845}
846