-
Notifications
You must be signed in to change notification settings - Fork 1
/
tcprsfil.cpp
1206 lines (1010 loc) · 32.9 KB
/
tcprsfil.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#ifdef RCSID
static char RCSid[] =
"";
#endif
/*
* Copyright (c) 1999, 2002 Michael J. Roberts. All Rights Reserved.
*
* Please see the accompanying license file, LICENSE.TXT, for information
* on using and copying this software.
*/
/*
Name
tcprssym.cpp - TADS 3 Compiler Parser, symbol file operations
Function
This parser module contains code that manages symbol and object files.
These routines aren't needed in interpreter builds with dynamic compilation
("eval()" support), so we isolate them out for separate linkage.
Notes
Modified
04/30/99 MJRoberts - Creation
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "os.h"
#include "t3std.h"
#include "tcprs.h"
#include "tctarg.h"
#include "tcgen.h"
#include "vmhash.h"
#include "tcmain.h"
#include "vmfile.h"
#include "tctok.h"
/* ------------------------------------------------------------------------ */
/*
* main parser symbol and object file operations
*/
/*
* Add a symbol loaded from an object file
*/
void CTcParser::add_sym_from_obj_file(uint idx, class CTcSymbol *sym)
{
/*
* add the entry to the object file index list - adjust from the
* 1-based index used in the file to an array index
*/
obj_sym_list_[idx - 1] = sym;
}
/*
* Get an object file symbol, ensuring that it's an object symbol
*/
CTcSymObj *CTcParser::get_objfile_objsym(uint idx)
{
CTcSymObj *sym;
/* get the object based on the index */
sym = (CTcSymObj *)get_objfile_sym(idx);
/* make sure it's an object - if it isn't, return null */
if (sym == 0 || sym->get_type() != TC_SYM_OBJ)
return 0;
/* it checks out - return it */
return sym;
}
/*
* Add a dictionary symbol loaded from an object file
*/
void CTcParser::add_dict_from_obj_file(CTcSymObj *sym)
{
CTcDictEntry *entry;
/* get the current entry, if any */
entry = get_dict_entry(sym);
/* if there's no current entry, create a new one */
if (entry == 0)
{
/* create the entry */
entry = create_dict_entry(sym);
}
/* add the entry to the object file index list */
obj_dict_list_[obj_file_dict_idx_++] = entry;
}
/* ------------------------------------------------------------------------ */
/*
* Base symbol class
*/
/*
* Write to a symbol file.
*/
int CTcSymbolBase::write_to_sym_file(CVmFile *fp)
{
/* do the basic writing */
return write_to_file_gen(fp);
}
/*
* Write to a file. This is a generic base routine that can be used for
* writing to a symbol or object file.
*/
int CTcSymbolBase::write_to_file_gen(CVmFile *fp)
{
/* write my type */
fp->write_uint2((int)get_type());
/* write my name */
return write_name_to_file(fp);
}
/*
* Write the symbol name to a file
*/
int CTcSymbolBase::write_name_to_file(CVmFile *fp)
{
/* write the length of my symbol name, followed by the symbol name */
fp->write_uint2((int)get_sym_len());
/* write the symbol string */
fp->write_bytes(get_sym(), get_sym_len());
/* we wrote the symbol */
return TRUE;
}
/*
* Read a symbol from a symbol file
*/
CTcSymbol *CTcSymbolBase::read_from_sym_file(CVmFile *fp)
{
/*
* read the type - this is the one thing we know is always present for
* every symbol (the rest of the data might vary per subclass)
*/
tc_symtype_t typ = (tc_symtype_t)fp->read_uint2();
/* create the object based on the type */
switch(typ)
{
case TC_SYM_FUNC:
return CTcSymFunc::read_from_sym_file(fp);
case TC_SYM_OBJ:
return CTcSymObj::read_from_sym_file(fp);
case TC_SYM_PROP:
return CTcSymProp::read_from_sym_file(fp);
case TC_SYM_ENUM:
return CTcSymEnum::read_from_sym_file(fp);
case TC_SYM_METACLASS:
return CTcSymMetaclass::read_from_sym_file(fp);
default:
/* other types should not be in a symbol file */
G_tcmain->log_error(0, 0, TC_SEV_ERROR, TCERR_SYMEXP_INV_TYPE);
return 0;
}
}
/*
* Read the basic information from the symbol file
*/
const char *CTcSymbolBase::base_read_from_sym_file(CVmFile *fp)
{
char buf[TOK_SYM_MAX_LEN + 1];
/* read, null-terminate, and return the string */
return CTcParser::read_len_prefix_str(fp, buf, sizeof(buf), 0,
TCERR_SYMEXP_SYM_TOO_LONG);
}
/*
* Write to an object file.
*/
int CTcSymbolBase::write_to_obj_file(CVmFile *fp)
{
/* do the basic writing */
return write_to_file_gen(fp);
}
/* ------------------------------------------------------------------------ */
/*
* Function symbols
*/
/*
* Write to a symbol file
*/
int CTcSymFuncBase::write_to_sym_file(CVmFile *fp)
{
char buf[7];
CTcSymFunc *cur;
int ext_modify;
/* scan for the bottom of our modify stack */
for (cur = get_mod_base() ; cur != 0 && cur->get_mod_base() != 0 ;
cur = cur->get_mod_base()) ;
/* we modify an external if the bottom of our modify stack is external */
ext_modify = (cur != 0 && cur->is_extern());
/*
* If we're external, don't bother writing to the file - if we're
* importing a function, we don't want to export it as well. Note that
* a function that is replacing or modifying an external function is
* fundamentally external itself, because the function must be defined
* in another file to be replaceable/modifiable.
*
* As an exception, if this is a multi-method base symbol, and a
* multi-method with this name is defined in this file, export it even
* though it's technically an extern symbol. We don't export most
* extern symbols because we count on the definer to export them, but
* in the case of multi-method base symbols, there is no definer - the
* base symbol is basically a placeholder to be filled in by the
* linker. So *someone* has to export these. The logical place to
* export them is from any file that defines a multi-method based on
* the base symbol.
*/
if ((is_extern_ || ext_replace_ || ext_modify) && !mm_def_)
return FALSE;
/* inherit default */
CTcSymbol::write_to_sym_file(fp);
/* write our argument count, varargs flag, and return value flag */
oswp2(buf, argc_);
oswp2(buf + 2, opt_argc_);
buf[4] = (varargs_ != 0);
buf[5] = (has_retval_ != 0);
buf[6] = (is_multimethod_ ? 1 : 0)
| (is_multimethod_base_ ? 2 : 0);
fp->write_bytes(buf, 7);
/* we wrote the symbol */
return TRUE;
}
/*
* Read from a symbol file
*/
CTcSymbol *CTcSymFuncBase::read_from_sym_file(CVmFile *fp)
{
char symbuf[4096];
const char *sym;
char info[7];
int argc;
int opt_argc;
int varargs;
int has_retval;
int is_multimethod, is_multimethod_base;
/*
* Read the symbol name. Use a custom reader instead of the base
* reader, because function symbols can be quite long, due to
* multimethod name decoration.
*/
if ((sym = CTcParser::read_len_prefix_str(
fp, symbuf, sizeof(symbuf), 0, TCERR_SYMEXP_SYM_TOO_LONG)) == 0)
return 0;
/*
* read the argument & optional argument count, varargs flag, and
* return value flag
*/
fp->read_bytes(info, 7);
argc = osrp2(info);
opt_argc = osrp2(info + 2);
varargs = (info[4] != 0);
has_retval = (info[5] != 0);
is_multimethod = ((info[6] & 1) != 0);
is_multimethod_base = ((info[6] & 2) != 0);
/* create and return the new symbol */
return new CTcSymFunc(sym, strlen(sym), FALSE, argc, opt_argc,
varargs, has_retval,
is_multimethod, is_multimethod_base, TRUE, TRUE);
}
/*
* Write to an object file
*/
int CTcSymFuncBase::write_to_obj_file(CVmFile *fp)
{
char buf[12];
CTcSymFunc *cur;
CTcSymFunc *last_mod;
int mod_body_cnt;
int ext_modify;
/*
* If it's external, and we have no fixups, don't bother writing it to
* the object file. If there are no fixups, we don't have any
* references to the function, hence there's no need to include it in
* the object file.
*/
if (is_extern_ && fixups_ == 0)
return FALSE;
/*
* If we have a modified base function, scan down the chain of modified
* bases until we reach the last one. If it's external, we need to
* note this, and we need to store the fixup list for the external
* symbol so that we can explicitly link it to the imported symbol at
* link time.
*/
for (mod_body_cnt = 0, last_mod = 0, cur = get_mod_base() ; cur != 0 ;
last_mod = cur, cur = cur->get_mod_base())
{
/* if this one has an associated code body, count it */
if (cur->get_code_body() != 0 && !cur->get_code_body()->is_replaced())
++mod_body_cnt;
}
/* we modify an external if the last in the modify chain is external */
ext_modify = (last_mod != 0 && last_mod->is_extern());
/* inherit default */
CTcSymbol::write_to_obj_file(fp);
/*
* write our argument count, varargs flag, return value, extern flags,
* and the number of our modified base functions with code bodies
*/
oswp2(buf, argc_);
oswp2(buf + 2, opt_argc_);
buf[4] = (varargs_ != 0);
buf[5] = (has_retval_ != 0);
buf[6] = (is_extern_ != 0);
buf[7] = (ext_replace_ != 0);
buf[8] = (ext_modify != 0);
buf[9] = (is_multimethod_ ? 1 : 0)
| (is_multimethod_base_ ? 2 : 0);
oswp2(buf + 10, mod_body_cnt);
fp->write_bytes(buf, 12);
/* if we modify an external, save its fixup list */
if (ext_modify)
CTcAbsFixup::write_fixup_list_to_object_file(fp, last_mod->fixups_);
/* write the code stream offsets of the modified base function bodies */
for (cur = get_mod_base() ; cur != 0 ; cur = cur->get_mod_base())
{
/* if this one has a code body, write its code stream offset */
if (cur->get_code_body() != 0)
fp->write_uint4(cur->get_anchor()->get_ofs());
}
/*
* If we're defined as external, write our fixup list. Since this
* is an external symbol, it will have no anchor in the code stream,
* hence we need to write our fixup list with the symbol and not
* with the anchor.
*/
if (is_extern_)
CTcAbsFixup::write_fixup_list_to_object_file(fp, fixups_);
/* we wrote the symbol */
return TRUE;
}
/* ------------------------------------------------------------------------ */
/*
* Object symbols
*/
/*
* Write to a symbol file
*/
int CTcSymObjBase::write_to_sym_file(CVmFile *fp)
{
int result;
/*
* If we're external, don't bother writing to the file - if we're
* importing an object, we don't want to export it as well. If it's
* modified, don't write it either, because modified symbols cannot be
* referenced directly by name (the symbol for a modified object is a
* fake symbol anyway). In addition, don't write the symbol if it's a
* 'modify' or 'replace' definition that applies to an external base
* object - instead, we'll pick up the symbol from the other symbol
* file with the original definition.
*/
if (is_extern_ || modified_ || ext_modify_ || ext_replace_)
return FALSE;
/* inherit default */
result = CTcSymbol::write_to_sym_file(fp);
/* if that was successful, write additional object-type-specific data */
if (result)
{
/* write the metaclass ID */
fp->write_uint2((int)metaclass_);
/* if it's of metaclass tads-object, write superclass information */
if (metaclass_ == TC_META_TADSOBJ)
{
char c;
size_t cnt;
CTPNSuperclass *sc;
/*
* set up our flags: indicate whether or not we're explicitly
* based on the root object class, and if we're a 'class'
* object
*/
c = ((sc_is_root() ? 1 : 0)
| (is_class() ? 2 : 0)
| (is_transient() ? 4 : 0));
fp->write_bytes(&c, 1);
/* count the declared superclasses */
for (cnt = 0, sc = sc_name_head_ ; sc != 0 ;
sc = sc->nxt_, ++cnt) ;
/*
* write the number of declared superclasses followed by the
* names of the superclasses
*/
fp->write_uint2(cnt);
for (sc = sc_name_head_ ; sc != 0 ; sc = sc->nxt_)
{
/* write the counted-length identifier */
fp->write_uint2(sc->get_sym_len());
fp->write_bytes(sc->get_sym_txt(), sc->get_sym_len());
}
}
}
/* return the result */
return result;
}
/*
* Read from a symbol file
*/
CTcSymbol *CTcSymObjBase::read_from_sym_file(CVmFile *fp)
{
const char *txt;
tc_metaclass_t meta;
CTcSymObj *sym;
char c;
size_t cnt;
size_t i;
/* read the symbol name */
if ((txt = base_read_from_sym_file(fp)) == 0)
return 0;
/* read the metaclass ID */
meta = (tc_metaclass_t)fp->read_uint2();
/*
* If it's a dictionary object, check to see if it's already defined -
* a dictionary object can be exported from multiple modules without
* error, since dictionaries are shared across modules.
*
* The same applies to grammar productions, since a grammar production
* can be implicitly created in multiple files.
*/
if (meta == TC_META_DICT || meta == TC_META_GRAMPROD)
{
/* look for a previous instance of the symbol */
CTcSymbol *old_sym =
G_prs->get_global_symtab()->find(txt, strlen(txt));
if (old_sym != 0
&& old_sym->get_type() == TC_SYM_OBJ
&& ((CTcSymObj *)old_sym)->get_metaclass() == meta)
{
/*
* the dictionary is already in the symbol table - return the
* existing one, since there's no conflict with importing the
* dictionary from multiple places
*/
return old_sym;
}
}
/* create the new symbol */
sym = new CTcSymObj(txt, strlen(txt), FALSE, G_cg->new_obj_id(),
TRUE, meta, 0);
/* if the metaclass is tads-object, read additional information */
if (meta == TC_META_TADSOBJ)
{
/* read the root-object-superclass flag and the class-object flag */
fp->read_bytes(&c, 1);
sym->set_sc_is_root((c & 1) != 0);
sym->set_is_class((c & 2) != 0);
if ((c & 4) != 0)
sym->set_transient();
/* read the number of superclasses, and read the superclass names */
cnt = fp->read_uint2();
for (i = 0 ; i < cnt ; ++i)
{
char buf[TOK_SYM_MAX_LEN + 1];
const char *sc_txt;
size_t sc_len;
/* read the symbol */
sc_txt = CTcParser::read_len_prefix_str(
fp, buf, sizeof(buf), &sc_len, TCERR_SYMEXP_SYM_TOO_LONG);
/* add the superclass list entry to the symbol */
sym->add_sc_name_entry(sc_txt, sc_len);
}
}
/* return the symbol */
return sym;
}
/*
* Write to a object file
*/
int CTcSymObjBase::write_to_obj_file(CVmFile *fp)
{
/*
* If the object is external and has never been referenced, don't
* bother writing it.
*
* In addition, if the object is marked as modified, don't write it.
* We write modified base objects specially, because we must control
* the order in which a modified base object is written relative its
* modifying object.
*/
if ((is_extern_ && !ref_) || modified_)
return FALSE;
/* if the object has already been written, don't write it again */
if (written_to_obj_)
{
/*
* if we've never been counted in the object file before, we must
* have been written indirectly in the course of writing another
* symbol - in this case, return true to indicate that we are in
* the file, even though we're not actually writing anything now
*/
if (!counted_in_obj_)
{
/* we've now been counted in the object file */
counted_in_obj_ = TRUE;
/* indicate that we have been written */
return TRUE;
}
else
{
/* we've already been written and counted - don't write again */
return FALSE;
}
}
/* do the main part of the writing */
return write_to_obj_file_main(fp);
}
/*
* Write the object symbol to an object file. This main routine does most
* of the actual work, once we've decided that we're actually going to
* write the symbol.
*/
int CTcSymObjBase::write_to_obj_file_main(CVmFile *fp)
{
/* take the next object file index */
set_obj_file_idx(G_prs->get_next_obj_file_sym_idx());
/*
* if I have a dictionary object, make sure it's in the object file
* before I am - we need to be able to reference the object during
* load, so it has to be written before me
*/
if (dict_ != 0)
dict_->write_sym_to_obj_file(fp);
/*
* if I'm not anonymous, write the basic header information for the
* symbol (don't do this for anonymous objects, since they don't have a
* name to write)
*/
if (!anon_)
write_to_file_gen(fp);
/*
* write my object ID, so that we can translate from the local
* numbering system in the object file to the new numbering system in
* the image file
*/
char buf[32];
oswp4(buf, obj_id_);
/* write the flags */
buf[4] = (is_extern_ != 0);
buf[5] = (ext_replace_ != 0);
buf[6] = (modified_ != 0);
buf[7] = (mod_base_sym_ != 0);
buf[8] = (ext_modify_ != 0);
buf[9] = (obj_stm_ != 0 && obj_stm_->is_class());
buf[10] = (transient_ != 0);
/* add the metaclass type */
oswp2(buf + 11, (int)metaclass_);
/* add the dictionary's object file index, if we have one */
if (dict_ != 0)
oswp2(buf + 13, dict_->get_obj_idx());
else
oswp2(buf + 13, 0);
/*
* add my object file index (we store this to eliminate any dependency
* on the load order - this allows us to write other symbols
* recursively without worrying about exactly where the recursion
* occurs relative to assigning the file index)
*/
oswp2(buf + 15, get_obj_file_idx());
/* write the data to the file */
fp->write_bytes(buf, 17);
/* if we're not external, write our stream address */
if (!is_extern_)
fp->write_uint4(stream_ofs_);
/* if we're modifying another object, store some extra information */
if (mod_base_sym_ != 0)
{
/*
* Write our list of properties to be deleted from base objects at
* link time. First, count the properties in the list.
*/
CTcObjPropDel *delprop;
int cnt;
for (cnt = 0, delprop = first_del_prop_ ; delprop != 0 ;
++cnt, delprop = delprop->nxt_) ;
/* write the count */
fp->write_uint2(cnt);
/* write the deleted property list */
for (delprop = first_del_prop_ ; delprop != 0 ;
delprop = delprop->nxt_)
{
/*
* write out this property symbol (we write the symbol rather
* than the ID, because when we load the object file, we'll
* need to adjust the ID to new global numbering system in the
* image file; the easiest way to do this is to write the
* symbol and look it up at load time)
*/
fp->write_uint2(delprop->prop_sym_->get_sym_len());
fp->write_bytes(delprop->prop_sym_->get_sym(),
delprop->prop_sym_->get_sym_len());
}
}
/* write our self-reference fixup list */
CTcIdFixup::write_to_object_file(fp, fixups_);
/*
* If this is a modifying object, we must write the entire chain of
* modified base objects immediately after this object. When we're
* reading the symbol table, this ensures that we can read each
* modified base object recursively as we read its modifiers, which is
* necessary so that we can build up the same modification chain on
* loading the object file.
*/
if (mod_base_sym_ != 0)
{
/* write the main part of the definition */
mod_base_sym_->write_to_obj_file_main(fp);
}
/* mark the object as written to the file */
written_to_obj_ = TRUE;
/* written */
return TRUE;
}
/*
* Write a modified object to an object file
*/
int CTcSymObjBase::write_to_obj_file_as_modified(class CVmFile *fp)
{
return write_to_obj_file_main(fp);
}
/*
* Write cross-references to the object file
*/
int CTcSymObjBase::write_refs_to_obj_file(CVmFile *fp)
{
CTPNSuperclass *sc;
uint cnt;
long cnt_pos;
long end_pos;
CTcVocabEntry *voc;
/*
* if this symbol wasn't written to the object file in the first place,
* we obviously don't want to include any extra data for it
*/
if (!written_to_obj_)
return FALSE;
/* write my symbol index */
fp->write_uint4(get_obj_file_idx());
/* write a placeholder superclass count */
cnt_pos = fp->get_pos();
fp->write_uint2(0);
/* write my superclass list */
for (sc = (obj_stm_ != 0 ? obj_stm_->get_first_sc() : 0), cnt = 0 ;
sc != 0 ; sc = sc->nxt_)
{
CTcSymObj *sym;
/* look up this superclass symbol */
sym = (CTcSymObj *)sc->get_sym();
if (sym != 0 && sym->get_type() == TC_SYM_OBJ)
{
/* write the superclass symbol index */
fp->write_uint4(sym->get_obj_file_idx());
/* count it */
++cnt;
}
}
/* go back and write the superclass count */
end_pos = fp->get_pos();
fp->set_pos(cnt_pos);
fp->write_uint2(cnt);
fp->set_pos(end_pos);
/* count my vocabulary words */
for (cnt = 0, voc = vocab_ ; voc != 0 ; ++cnt, voc = voc->nxt_) ;
/* write my vocabulary words */
fp->write_uint2(cnt);
for (voc = vocab_ ; voc != 0 ; voc = voc->nxt_)
{
/* write the text of the word */
fp->write_uint2(voc->len_);
fp->write_bytes(voc->txt_, voc->len_);
/* write the property ID */
fp->write_uint2(voc->prop_);
}
/* indicate that we wrote the symbol */
return TRUE;
}
/*
* Load references from the object file
*/
void CTcSymObjBase::load_refs_from_obj_file(CVmFile *fp, const char *,
tctarg_obj_id_t *,
tctarg_prop_id_t *prop_xlat)
{
uint i;
uint cnt;
CTcObjScEntry *sc_tail;
/* read the superclass count */
cnt = fp->read_uint2();
/* read the superclass list */
for (sc_tail = 0, i = 0 ; i < cnt ; ++i)
{
ulong idx;
CTcSymObj *sym;
CTcObjScEntry *sc;
/* read the next index */
idx = fp->read_uint4();
/* get the symbol */
sym = (CTcSymObj *)G_prs->get_objfile_sym(idx);
if (sym->get_type() != TC_SYM_OBJ)
sym = 0;
/* create a new list entry */
sc = new (G_prsmem) CTcObjScEntry(sym);
/* link it in at the end of the my superclass list */
if (sc_tail != 0)
sc_tail->nxt_ = sc;
else
sc_ = sc;
/* this is now the last entry in my superclass list */
sc_tail = sc;
}
/* load the vocabulary words */
cnt = fp->read_uint2();
for (i = 0 ; i < cnt ; ++i)
{
size_t len;
char *txt;
tctarg_prop_id_t prop;
/* read the length of this word's text */
len = fp->read_uint2();
/* allocate parser memory for the word's text */
txt = (char *)G_prsmem->alloc(len);
/* read the word into the allocated text buffer */
fp->read_bytes(txt, len);
/* read the property */
prop = (tctarg_prop_id_t)fp->read_uint2();
/* translate the property to the new numbering system */
prop = prop_xlat[prop];
/* add the word to our vocabulary */
add_vocab_word(txt, len, prop);
}
}
/* ------------------------------------------------------------------------ */
/*
* Property symbols
*/
/*
* Write to a symbol file
*/
int CTcSymPropBase::write_to_sym_file(CVmFile *fp)
{
/* inherit the default handling */
int ret = CTcSymbol::write_to_sym_file(fp);
if (ret)
{
/* encode and write our flags */
char flags = 0;
if (ref_)
flags |= 1;
if (vocab_)
flags |= 2;
if (weak_)
flags |= 4;
fp->write_byte(flags);
}
return ret;
}
/*
* Read from a symbol file
*/
CTcSymbol *CTcSymPropBase::read_from_sym_file(CVmFile *fp)
{
/* read the symbol name */
const char *sym;
if ((sym = base_read_from_sym_file(fp)) == 0)
return 0;
/* read and decode the flags of interest */
char flags = fp->read_byte();
int weak = flags & 4;
/*
* If this property is already defined, this is a harmless redefinition
* - every symbol file can define the same property without any
* problem. Indicate the harmless redefinition by returning the
* original symbol.
*/
CTcSymbol *old_entry = G_prs->get_global_symtab()->find(sym, strlen(sym));
if (old_entry != 0 && old_entry->get_type() == TC_SYM_PROP)
return old_entry;
/*
* if there's an old entry of a different type, and our entry is weak,
* the other symbol overrides our property definition
*/
if (old_entry != 0 && weak)
return old_entry;
/* create and return the new symbol */
CTcSymProp *prop_entry =
new CTcSymProp(sym, strlen(sym), FALSE, G_cg->new_prop_id());
/* if our definition is weak, record that */
if (weak)
prop_entry->set_weak(TRUE);
/* return the new entry */
return prop_entry;
}
/*
* Write to an object file
*/
int CTcSymPropBase::write_to_obj_file(CVmFile *fp)
{
/*
* If the property has never been referenced, don't bother writing it.
* We must have picked up the definition from an external symbol set we
* loaded but have no references of our own to the property.
*/
if (!ref_)
return FALSE;
/* inherit default */
CTcSymbol::write_to_obj_file(fp);
/*
* write my local property ID value - when we load the object file,
* we'll need to figure out the translation from our original numbering
* system to the new numbering system used in the final image file
*/
fp->write_uint4((ulong)prop_);
/* written */
return TRUE;
}
/* ------------------------------------------------------------------------ */
/*
* Enumerator symbol
*/
/*
* Write to a symbol file
*/
int CTcSymEnumBase::write_to_sym_file(CVmFile *fp)
{
int result;
char buf[32];
/* inherit default */
result = CTcSymbol::write_to_sym_file(fp);
/* write the 'token' flag */
if (result)
{
/* clear the flags */
buf[0] = 0;
/* set the 'token' flag if appropriate */
if (is_token_)
buf[0] |= 1;
/* write the flags */
fp->write_bytes(buf, 1);
}
/* return the result */
return result;
}
/*
* Read from a symbol file
*/
CTcSymbol *CTcSymEnumBase::read_from_sym_file(CVmFile *fp)
{
const char *sym;
CTcSymEnum *old_entry;
char buf[32];
int is_token;
/* read the symbol name */
if ((sym = base_read_from_sym_file(fp)) == 0)
return 0;
/* read the 'token' flag */
fp->read_bytes(buf, 1);
is_token = ((buf[0] & 1) != 0);