Fix warnings from compiling with gcc 4.3.0
[dyninst.git] / common / src / serialize-bin.C
1
2 /*
3  * Copyright (c) 1996-2007 Barton P. Miller
4  * 
5  * We provide the Paradyn Parallel Performance Tools (below
6  * described as "Paradyn") on an AS IS basis, and do not warrant its
7  * validity or performance.  We reserve the right to update, modify,
8  * or discontinue this software at any time.  We shall have no
9  * obligation to supply such updates or modifications or any other
10  * form of support to you.
11  * 
12  * By your use of Paradyn, you understand and agree that we (or any
13  * other person or entity with proprietary rights in Paradyn) are
14  * under no obligation to provide either maintenance services,
15  * update services, notices of latent defects, or correction of
16  * defects for Paradyn.
17  * 
18  * This library is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU Lesser General Public
20  * License as published by the Free Software Foundation; either
21  * version 2.1 of the License, or (at your option) any later version.
22  * 
23  * This library is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26  * Lesser General Public License for more details.
27  * 
28  * You should have received a copy of the GNU Lesser General Public
29  * License along with this library; if not, write to the Free Software
30  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
31  */
32
33 #include <stdio.h>
34 #include <vector>
35
36 #include "dynutil/h/dyntypes.h"
37 #include "common/h/serialize.h"
38 #include "common/h/Types.h"
39
40
41 using namespace Dyninst;
42
43 DLLEXPORT dyn_hash_map<Address, AnnotatableBase *> SerDesBin::annotatable_id_map;
44
45
46 DLLEXPORT dyn_hash_map<std::string, SerializerBase::subsystem_serializers_t> SerializerBase::all_serializers;
47
48
49 bool dyn_debug_serializer = false;
50 bool &serializer_debug_flag()
51 {
52    //  This function exists to get around problems with exporting the variable
53    //  across library boundaries on windows...   there's probably a better way to do this...
54    return dyn_debug_serializer;
55 }
56
57 void serialize_debug_init()
58 {
59    char *p;
60    if ( (p=getenv("DYNINST_DEBUG_SERIALIZER"))) {
61       fprintf(stderr, "Enabling DyninstAPI serializer debug\n");
62       dyn_debug_serializer = true;
63    }
64 }
65
66 int serializer_printf(const char *format, ...) 
67 {   
68    if (!dyn_debug_serializer) return 0;
69    if (NULL == format) return -1;
70
71    //debugPrintLock->_Lock(FILE__, __LINE__);
72
73    //  probably want to have basic thread-id routines in libcommon...
74    //  uh...  later....
75
76    //fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
77    va_list va;
78    va_start(va, format);
79    int ret = vfprintf(stderr, format, va);
80    va_end(va);
81
82    //debugPrintLock->_Unlock(FILE__, __LINE__);
83
84    return ret;
85
86
87 void printSerErr(const SerializerError &err) 
88 {
89    fprintf(stderr, "\tserializer exception %s from \n\t%s[%d]\n", 
90          err.what(), err.file().c_str(), err.line());
91 }
92
93 void trans_adapt(SerializerBase *ser, Serializable &it, const char *tag)
94 {
95    it.serialize(ser, tag);
96 }
97
98 void trans_adapt(SerializerBase *ser, Serializable  *itp, const char *tag)
99 {
100    assert(itp);
101    trans_adapt(ser, *itp, tag);
102 }
103
104 void trans_adapt(SerializerBase *ser, bool &it, const char *tag)
105 {
106    assert(ser);
107    ser->translate_base(it, tag);
108 }
109
110 void trans_adapt(SerializerBase *ser, int &it, const char *tag)
111 {
112    assert(ser);
113    ser->translate_base(it, tag);
114 }
115
116 void trans_adapt(SerializerBase *ser, unsigned int &it, const char *tag)
117 {
118    assert(ser);
119    ser->translate_base(it, tag);
120 }
121
122 void trans_adapt(SerializerBase *ser, long &it, const char *tag)
123 {
124    assert(ser);
125    ser->translate_base(it, tag);
126 }
127
128 void trans_adapt(SerializerBase *ser, unsigned long &it, const char *tag)
129 {
130    assert(ser);
131    ser->translate_base(it, tag);
132 }
133
134 void trans_adapt(SerializerBase *ser, char &it, const char *tag)
135 {
136    assert(ser);
137    ser->translate_base(it, tag);
138 }
139
140 void trans_adapt(SerializerBase *ser, char *&it, const char *tag)
141 {
142    assert(ser);
143    assert(it);
144    int s_len = strlen(it);
145    ser->translate_base(const_cast<const char *&>(it), s_len, tag);
146 }
147
148 void trans_adapt(SerializerBase *ser, std::string &it, const char *tag)
149 {
150    assert(ser);
151    ser->translate_base(it, tag);
152 }
153
154 void trans_adapt(SerializerBase *ser, float &it, const char *tag)
155 {
156    assert(ser);
157    ser->translate_base(it, tag);
158 }
159
160 void trans_adapt(SerializerBase *ser, double  &it, const char *tag)
161 {
162    assert(ser);
163    ser->translate_base(it, tag);
164 }
165
166 DLLEXPORT bool ifxml_start_element(SerializerBase *sb, const char *tag)
167 {
168    SerializerXML *sxml = dynamic_cast<SerializerXML *>(sb);
169    if (!sxml) {
170       return false;
171    }
172
173    if (sxml->iomode() == sd_deserialize) {
174       fprintf(stderr, "%s[%d]:  ERROR:  request to deserialize xml\n", FILE__, __LINE__);
175       return false;
176    }
177
178    sxml->getSD_xml().start_element(tag);
179
180    return true;
181 }
182
183 DLLEXPORT bool ifxml_end_element(SerializerBase *sb, const char * /*tag*/)
184 {
185    SerializerXML *sxml = dynamic_cast<SerializerXML *>(sb);
186    if (!sxml) {
187       return false;
188    }
189
190    if (sxml->iomode() == sd_deserialize) {
191       fprintf(stderr, "%s[%d]:  ERROR:  request to deserialize xml\n", FILE__, __LINE__);
192       return false;
193    }
194
195    sxml->getSD_xml().end_element();
196
197    return true;
198 }
199
200 SerDesBin &SerializerBin::getSD_bin()
201 {
202    SerDes &sd = getSD();
203    SerDesBin *sdbin = dynamic_cast<SerDesBin *> (&sd);
204    assert(sdbin);
205    return *sdbin;
206 }
207
208 bool SerializerBin::global_disable = false;
209 dyn_hash_map<const char *, SerializerBin *> SerializerBin::active_bin_serializers;
210
211 void SerializerBin::dumpActiveBinSerializers()
212 {
213    fprintf(stderr, "%s[%d]:  have serializers:\n", FILE__, __LINE__);
214
215    dyn_hash_map<const char *, SerializerBin *>::iterator iter;
216
217    for (iter = active_bin_serializers.begin(); 
218          iter != active_bin_serializers.end(); 
219          iter++)
220    {
221       fprintf(stderr, "\t%s--%p\n", iter->first, iter->second);
222    }
223 }
224
225 SerializerBin::SerializerBin(const char *name_, std::string filename, 
226       iomode_t dir, bool verbose) :
227    SerializerBase(name_, filename, dir, verbose) 
228 {
229    if (global_disable) 
230    {
231       fprintf(stderr, "%s[%d]:  Failing to construct Bin Translator:  global disable set\n", 
232             FILE__, __LINE__);
233
234       throw SerializerError(FILE__, __LINE__, 
235             std::string("serialization disabled"), 
236             SerializerError::ser_err_disabled);
237    }
238
239    dyn_hash_map<const char *, SerializerBin *>::iterator iter;
240
241    iter = active_bin_serializers.find(name_);
242
243    if (iter == active_bin_serializers.end()) 
244    {
245       fprintf(stderr, "%s[%d]:  Adding Active serializer for name %s\n", 
246             FILE__, __LINE__, name_);
247
248       active_bin_serializers[name_] = this;
249    }
250    else
251    {
252       fprintf(stderr, "%s[%d]:  Weird, already have active serializer for name %s\n", 
253             FILE__, __LINE__, name_);
254    }
255
256 }
257
258 SerializerBin::~SerializerBin()
259 {
260    dyn_hash_map<const char *, SerializerBin *>::iterator iter;
261
262    iter = active_bin_serializers.find(name().c_str());
263
264    if (iter == active_bin_serializers.end()) 
265    {
266       fprintf(stderr, "%s[%d]:  Weird, no static ptr for name %s\n", 
267             FILE__, __LINE__, name().c_str());
268    }
269    else
270    {
271       fprintf(stderr, "%s[%d]:  Removing active serializer for name %s\n", 
272             FILE__, __LINE__, name().c_str());
273       active_bin_serializers.erase(iter);
274    }
275 }
276
277 SerializerBin *SerializerBin::findSerializerByName(const char *name_)
278 {
279    dyn_hash_map<const char *, SerializerBin *>::iterator iter;
280
281    iter = active_bin_serializers.find(name_);
282
283    if (iter == active_bin_serializers.end()) 
284    {
285       fprintf(stderr, "%s[%d]:  No static ptr for name %s\n", 
286             FILE__, __LINE__, name_);
287       dumpActiveBinSerializers();
288    }
289    else
290    {
291       fprintf(stderr, "%s[%d]:  Found active serializer for name %s\n", 
292             FILE__, __LINE__, name_);
293
294       return iter->second;
295    }
296
297    return NULL;
298 }
299
300 void SerializerBin::globalDisable()
301 {
302    global_disable = true;
303 }
304
305 void SerializerBin::globalEnable()
306 {
307    global_disable = false;
308 }
309
310 FILE *SerDesBin::init(std::string filename, iomode_t mode, bool /*verbose*/) 
311 {
312    if (SerializerBin::global_disable) {
313       fprintf(stderr, "%s[%d]:  Failing to construct Bin Translator:  global disable set\n", FILE__, __LINE__);
314       throw SerializerError(FILE__, __LINE__, 
315             std::string("serialization disabled"), 
316             SerializerError::ser_err_disabled);
317    }
318
319    FILE *f = NULL;
320    //  NOTE:  fname is path-resolved and turned into "filename" by the SerDes ctor
321    std::string cache_name;
322    if (! SerDesBin::resolveCachePath(filename, cache_name)) {
323       fprintf(stderr, "%s[%d]:  no cache file exists for %s\n", 
324             FILE__, __LINE__, filename.c_str());
325       if (mode == sd_deserialize) {
326          //  can't deserialize from a file that does not exist
327          char msg[128];
328          sprintf(msg, "%s[%d]:  no cache file exists for %s\n", 
329                FILE__, __LINE__, filename.c_str());
330          SER_ERR(msg);
331       }
332    }
333
334    fprintf(stderr, "%s[%d]:  opening cache file %s\n", FILE__, __LINE__, cache_name.c_str());
335    f = fopen(cache_name.c_str(), (mode == sd_serialize) ? "w+" : "r");
336    if (!f) {
337       char msg[128];
338       fprintf(stderr, "%s[%d]: fopen(%s, %s): %s\n", FILE__, __LINE__, 
339             cache_name.c_str(), (mode == sd_serialize) ? "w+" : "r", strerror(errno));
340       sprintf(msg, "fopen(%s, %s): %s", cache_name.c_str(), 
341             (mode == sd_serialize) ? "w+" : "r", strerror(errno));
342       SER_ERR(msg);
343    }
344
345    fprintf(stderr, "%s[%d]:  opened cache file %s\n", FILE__, __LINE__, cache_name.c_str());
346
347    try {
348       if (mode == sd_serialize){
349          writeHeaderPreamble(f, filename, cache_name);
350       }
351       else {
352          readHeaderAndVerify(filename, cache_name, f);
353       }
354    }
355    catch(const SerializerError &err) {
356       fclose(f);
357       fprintf(stderr, "%s[%d]:  %sserialize failed init...  \n\t%s[%d]: %s\n\trethrowing...\n",
358             FILE__, __LINE__, mode == sd_serialize ? "" : "de", 
359             err.file().c_str(), err.line(), err.what());
360       throw(err);
361    }
362
363    return f;
364 }
365
366 SerDesBin::~SerDesBin()
367 {
368 }
369
370 bool SerDesBin::getDefaultCacheDir(std::string &path)
371 {
372    char *home_dir = getenv("HOME");
373    if (!home_dir) {
374       fprintf(stderr, "%s[%d]:  weird, no $HOME dir\n", FILE__, __LINE__);
375       return false;
376    }
377
378    std::string dot_dyninst_dir = std::string(home_dir) + std::string("/")
379       + std::string(DEFAULT_DYNINST_DIR);
380
381    struct stat statbuf;
382    if (0 != stat(dot_dyninst_dir.c_str(), &statbuf)) {
383       if (errno == ENOENT) {
384 #if defined (os_windows)
385          if (0 != mkdir(dot_dyninst_dir.c_str())) {
386             fprintf(stderr, "%s[%d]:  failed to make %s\n", FILE__, __LINE__, 
387                   dot_dyninst_dir.c_str(), strerror(errno));
388             return false;
389          } 
390 #else
391          if (0 != mkdir(dot_dyninst_dir.c_str(), S_IRWXU)) {
392             fprintf(stderr, "%s[%d]:  failed to make %s: %s\n", FILE__, __LINE__, 
393                   dot_dyninst_dir.c_str(), strerror(errno));
394             return false;
395          } 
396 #endif
397       }
398       else {
399          fprintf(stderr, "%s[%d]:  stat(%s) failed: %s\n", FILE__, __LINE__, 
400                dot_dyninst_dir.c_str(), strerror(errno));
401          return false;
402       }
403    }
404    else {
405 #if !defined (os_windows)
406       //  sanity check that its a dir
407       if (!S_ISDIR(statbuf.st_mode)) {
408          fprintf(stderr, "%s[%d]:  ERROR:  %s is not a dir\n", FILE__, __LINE__, 
409                dot_dyninst_dir.c_str());
410          return false;
411       }
412 #else
413       //  windows equiv to S_ISDIR??
414 #endif
415    }
416
417    path = dot_dyninst_dir + std::string("/") + std::string(DEFAULT_CACHE_DIR);
418
419    if (0 != stat(path.c_str(), &statbuf)) {
420       if (errno == ENOENT) {
421 #if defined (os_windows)
422          if (0 != mkdir(path.c_str())) {
423             fprintf(stderr, "%s[%d]:  failed to make %s\n", FILE__, __LINE__, 
424                   path.c_str(), strerror(errno));
425             return false;
426          } 
427 #else
428          if (0 != mkdir(path.c_str(), S_IRWXU)) {
429             fprintf(stderr, "%s[%d]:  failed to make %s: %s\n", FILE__, __LINE__, 
430                   path.c_str(), strerror(errno));
431             return false;
432          } 
433 #endif
434       }
435       else {
436          fprintf(stderr, "%s[%d]:  stat(%s) failed: %s\n", FILE__, __LINE__, 
437                path.c_str(), strerror(errno));
438          return false;
439       }
440    }
441    else {
442 #if !defined (os_windows)
443       //  sanity check that its a dir
444       if (!S_ISDIR(statbuf.st_mode)) {
445          fprintf(stderr, "%s[%d]:  ERROR:  %s is not a dir\n", FILE__, __LINE__, 
446                path.c_str());
447          return false;
448       }
449 #else
450       //  windows equiv to S_ISDIR??
451 #endif
452    }
453    fprintf(stderr, "%s[%d]:  using default cache dir: %s\n", FILE__, __LINE__, path.c_str());
454    return true;
455 }
456
457 bool SerDesBin::resolveCachePath(std::string full_file_path, std::string &cache_name)
458 {
459    std::string path;
460    char *path_dir = getenv(CACHE_DIR_VAR); 
461    if (!path_dir) {
462       if (!getDefaultCacheDir(path)) {
463          fprintf(stderr, "%s[%d]:  weird, failed to make $HOME/.dyninst/caches\n",
464                FILE__, __LINE__);
465          return false;
466       }
467    }
468
469    // get size of file (this is encoded into cache name)
470    struct stat statbuf;
471    if (0 != stat(full_file_path.c_str(), &statbuf)) {
472       fprintf(stderr, "%s[%d]:  stat %s failed: %s\n", FILE__, __LINE__, 
473             full_file_path.c_str(), strerror(errno));
474       return false;
475    }
476
477    std::string short_name = extract_pathname_tail(full_file_path);
478    fprintf(stderr, "%s[%d]:  file %s short name: %s\n", FILE__, __LINE__, 
479          full_file_path.c_str(), short_name.c_str());
480
481    // construct cache name from cache path, cache prefix, short name, and size
482    char sizestr[16];
483    sprintf(sizestr, "%d", (int)statbuf.st_size);
484    cache_name = path + std::string("/") + std::string(CACHE_PREFIX) + short_name 
485       + std::string("_") 
486       + std::string(sizestr);
487
488    fprintf(stderr, "%s[%d]:  constructed cache name: %s\n", FILE__, __LINE__, cache_name.c_str());
489    if (0 != stat(cache_name.c_str(), &statbuf)) {
490       if (errno != ENOENT) {
491          //  Its OK if the file doesn't exist, but complain if we get a different
492          // error
493          fprintf(stderr, "%s[%d]:  stat %s failed: %s\n", FILE__, __LINE__, 
494                cache_name.c_str(), strerror(errno));
495       }
496       fprintf(stderr, "%s[%d]:  cache file %s does not exist\n", FILE__, __LINE__, 
497             cache_name.c_str());
498       return false;
499    }
500
501    fprintf(stderr, "%s[%d]:  cache file %s exists\n", FILE__, __LINE__, cache_name.c_str());
502    return true;
503 }
504
505 bool SerDesBin::cacheFileExists(std::string fname)
506 {
507    std::string cache_name;
508    return resolveCachePath(fname, cache_name); 
509 }
510
511 void SerDesBin::readHeaderAndVerify(std::string full_file_path, std::string cache_name, FILE *fptr)
512 {
513    struct stat statbuf;
514
515    if (0 != stat(full_file_path.c_str(), &statbuf)) {
516       char msg[128];
517       if (errno != ENOENT) {
518          //  Its OK if the file doesn't exist, but complain if we get a different
519          // error
520          sprintf(msg, "%s[%d]:  stat %s failed: %s\n", FILE__, __LINE__, 
521                full_file_path.c_str(), strerror(errno));
522       }
523       SER_ERR(msg);
524    }
525
526    FILE *f = NULL;
527    if (fptr) 
528       f = fptr;
529    else {
530       f = fopen(cache_name.c_str(), "r");
531       if (!f) {
532          char msg[128];
533          sprintf(msg, "%s[%d]:  failed to open file %s: %s\n", 
534                FILE__, __LINE__, full_file_path.c_str(), strerror(errno));
535          SER_ERR(msg);
536       }
537    }
538
539    size_t source_file_size = statbuf.st_size;
540
541    cache_header_t header;
542    int rc = fread(&header, sizeof(cache_header_t), 1, f);
543    if (1 != rc) {
544       char msg[128];
545       sprintf(msg, "%s[%d]:  failed to read header struct for %s: %s\n", 
546             FILE__, __LINE__, cache_name.c_str(), strerror(errno));
547       SER_ERR(msg);
548    }
549
550    if (header.cache_magic != (unsigned) CACHE_MAGIC) {
551       char msg[128];
552       sprintf(msg, "%s[%d]:  magic number check failure for %s--%s: got %d, expected %d\n", 
553             FILE__, __LINE__, full_file_path.c_str(), cache_name.c_str(), header.cache_magic, CACHE_MAGIC);
554       SER_ERR(msg);
555    }
556
557    if (header.source_file_size != source_file_size) {
558       char msg[128];
559       sprintf(msg, "%s[%d]:  size discrepancy found for %s/%s\n", 
560             FILE__, __LINE__, full_file_path.c_str(), cache_name.c_str());
561       SER_ERR(msg);
562    }
563
564    if (!verifyChecksum(full_file_path, header.sha1)) {
565       char msg[128];
566       sprintf(msg, "%s[%d]:  checksum discrepancy found for %s/%s\n", 
567             FILE__, __LINE__, full_file_path.c_str(), cache_name.c_str());
568
569       if (!invalidateCache(cache_name)) {
570          fprintf(stderr, "%s[%d]:  failed to invalidate cache for file %s/%s\n", 
571                FILE__, __LINE__, full_file_path.c_str(), cache_name.c_str());
572       }
573
574       SER_ERR(msg);
575    }
576
577    if (!fptr)
578       fclose (f);
579 }
580
581
582 void SerDesBin::writeHeaderPreamble(FILE *f, std::string full_file_path, std::string /*cache_name*/)
583 {
584    fprintf(stderr, "%s[%d]:  welcome to write header preamble for %s\n", FILE__, __LINE__, full_file_path.c_str());
585
586    //  get a few bits of info on this file to construct the header of the cache
587    //  file...  checksum, size, ...  not mtime, since we don't care if someone 
588    //  copies the file around
589
590    struct stat statbuf;
591    if (0 != stat(full_file_path.c_str(), &statbuf)) {
592       char msg[128];
593       sprintf(msg, "%s[%d]:  stat %s failed: %s\n", FILE__, __LINE__, 
594             full_file_path.c_str(), strerror(errno));
595       SER_ERR(msg);
596    }
597
598    cache_header_t header;
599    header.cache_magic = CACHE_MAGIC;
600    header.source_file_size = statbuf.st_size;
601
602    if (NULL == sha1_file(full_file_path.c_str(), header.sha1)) {
603       char msg[128];
604       sprintf(msg, "sha1_file failed\n");
605       SER_ERR(msg);
606    }
607
608    int rc = fwrite(&header, sizeof(cache_header_t), 1, f);
609
610    if (1 != rc) 
611       SER_ERR("fwrite");
612
613 }
614
615 bool SerDesBin::verifyChecksum(std::string &full_file_path, 
616       const char comp_checksum[SHA1_DIGEST_LEN])
617 {
618    char new_checksum[SHA1_DIGEST_LEN]; 
619    if (NULL == sha1_file(full_file_path.c_str(), new_checksum)) {
620       fprintf(stderr, "%s[%d]:  sha1_file(%s) failed \n", 
621             FILE__, __LINE__, full_file_path.c_str());
622       return false;
623    }
624
625    if (strncmp(comp_checksum, new_checksum, SHA1_DIGEST_LEN)) {
626       fprintf(stderr, "%s[%d]:  sha1_file(%s): checksum mismatch: \n\told: %s\n\tnew:%s\n", 
627             FILE__, __LINE__, full_file_path.c_str(), comp_checksum, new_checksum);
628       return false;
629    }
630
631    return true;
632 }
633
634 bool SerDesBin::invalidateCache(std::string cache_name) 
635 {
636    if (-1 == unlink(cache_name.c_str())) {
637       fprintf(stderr, "%s[%d]:  unlink(%s): %s\n", FILE__, __LINE__, 
638             cache_name.c_str(), strerror(errno));
639       return false;
640    }
641
642    return true;
643 }
644
645 void SerDesBin::file_start(std::string &/*full_file_path*/)
646 {
647 }
648
649 void SerDesBin::vector_start(unsigned int &size, const char *) DECLTHROW (SerializerError)
650 {
651    //  before reading/writing a vector, we need to read its size
652    //  (so we know how many elements to read/alloc on deserialize
653    translate(size);
654 }
655
656 void SerDesBin::vector_end()
657 {
658    //  don't need to do anything
659 }
660
661 void SerDesBin::multimap_start(unsigned int &size, const char *) DECLTHROW (SerializerError)
662 {
663    //  before reading/writing a multimap, we need to read its size
664    //  (so we know how many elements to read/alloc on deserialize
665    translate(size);
666 }
667
668 void SerDesBin::multimap_end()
669 {
670    //  don't need to do anything
671 }
672
673 void SerDesBin::hash_map_start(unsigned int &size, const char *) DECLTHROW (SerializerError)
674 {
675    //  before reading/writing a hash map, we need to read its size
676    //  (so we know how many elements to read/alloc on deserialize
677    translate(size);
678 }
679
680 void SerDesBin::hash_map_end() 
681 {
682 }
683
684 void SerDesBin::annotation_start(const char *, const char *)
685 {
686 }
687
688 void SerDesBin::annotation_end()
689 {
690    //  don't need to do anything
691 }
692
693 void SerDesBin::translate(bool &param, const char *tag)
694 {
695    int rc;
696    if (iomode_ == sd_serialize) {
697       rc = fwrite(&param, sizeof(bool), 1, f);
698
699       if (1 != rc) 
700          SER_ERR("fwrite");
701    }
702    else {
703       rc = fread(&param, sizeof(bool), 1, f);
704
705       if (1 != rc) 
706          SER_ERR("fread");
707    }
708
709    if (noisy)
710       fprintf(stderr, "%s[%d]:  %sserialize %s=%s\n", FILE__, __LINE__,
711             iomode_ == sd_serialize ? "" : "de", 
712             tag ? tag : "no-tag",
713             param ? "true": "false");
714 }
715
716 void SerDesBin::translate(char &param, const char *tag)
717 {
718    int rc;
719    if (iomode_ == sd_serialize) {
720       rc = fwrite(&param, sizeof(char), 1, f);
721
722       if (1 != rc) 
723          SER_ERR("fwrite");
724    }
725    else {
726       rc = fread(&param, sizeof(char), 1, f);
727
728       if (1 != rc) 
729          SER_ERR("fread");
730    }
731
732    if (noisy)
733       fprintf(stderr, "%s[%d]:  %sserialize %s=%c\n", FILE__, __LINE__,
734             iomode_ == sd_serialize ? "" : "de", 
735             tag ? tag : "no-tag", param);
736 }
737
738 void SerDesBin::translate(int &param, const char *tag)
739 {
740    int rc;
741    if (iomode_ == sd_serialize) {
742       rc = fwrite(&param, sizeof(int), 1, f);
743
744       if (1 != rc) 
745          SER_ERR("fwrite");
746    }
747    else {
748       rc = fread(&param, sizeof(int), 1, f);
749
750       if (1 != rc) 
751          SER_ERR("fread");
752    }
753
754    if (noisy)
755       fprintf(stderr, "%s[%d]:  %sserialize %s=%d\n", FILE__, __LINE__,
756             iomode_ == sd_serialize ? "" : "de", 
757             tag ? tag : "no-tag", param);
758 }
759
760 void SerDesBin::translate(long &param, const char *tag)
761 {
762    int rc;
763    if (iomode_ == sd_serialize) {
764       rc = fwrite(&param, sizeof(long), 1, f);
765
766       if (1 != rc) 
767          SER_ERR("fwrite");
768    }
769    else {
770       rc = fread(&param, sizeof(long), 1, f);
771
772       if (1 != rc) 
773          SER_ERR("fread");
774    }
775
776    if (noisy)
777       fprintf(stderr, "%s[%d]:  %sserialize %s=%lu\n", FILE__, __LINE__,
778             iomode_ == sd_serialize ? "" : "de", 
779             tag ? tag : "no-tag", param);
780 }
781
782 void SerDesBin::translate(short &param, const char *tag)
783 {
784    int rc;
785    if (iomode_ == sd_serialize) {
786       rc = fwrite(&param, sizeof(short), 1, f);
787
788       if (1 != rc) 
789          SER_ERR("fwrite");
790    }
791    else {
792       rc = fread(&param, sizeof(short), 1, f);
793
794       if (1 != rc) 
795          SER_ERR("fread");
796    }
797
798    if (noisy)
799       fprintf(stderr, "%s[%d]:  %sserialize %s=%d\n", FILE__, __LINE__,
800             iomode_ == sd_serialize ? "" : "de", 
801             tag ? tag : "no-tag", param);
802 }
803
804 void SerDesBin::translate(unsigned int &param, const char * tag)
805 {
806    //  overkill for a typecast??
807    translate( (int &) param, tag);
808 }
809
810 void SerDesBin::translate(float &param, const char *tag)
811 {
812    int rc;
813    if (iomode_ == sd_serialize) {
814       rc = fwrite(&param, sizeof(float), 1, f);
815
816       if (1 != rc) 
817          SER_ERR("fwrite");
818    }
819    else {
820       rc = fread(&param, sizeof(float), 1, f);
821
822       if (1 != rc) 
823          SER_ERR("fread");
824    }
825
826    if (noisy)
827       fprintf(stderr, "%s[%d]:  %sserialize %s=%e\n", FILE__, __LINE__,
828             iomode_ == sd_serialize ? "" : "de", 
829             tag ? tag : "no-tag", param);
830 }
831
832 void SerDesBin::translate(double &param, const char *tag)
833 {
834    int rc;
835    if (iomode_ == sd_serialize) {
836       rc = fwrite(&param, sizeof(double), 1, f);
837
838       if (1 != rc) 
839          SER_ERR("fwrite");
840    }
841    else {
842       rc = fread(&param, sizeof(double), 1, f);
843
844       if (1 != rc) 
845          SER_ERR("fread");
846    }
847
848    if (noisy)
849       fprintf(stderr, "%s[%d]:  %sserialize %s=%g\n", FILE__, __LINE__,
850             iomode_ == sd_serialize ? "" : "de", 
851             tag ? tag : "no-tag", param);
852 }
853
854 void SerDesBin::translate(Address &param, const char *tag)
855 {
856    int rc;
857    if (iomode_ == sd_serialize) {
858       rc = fwrite(&param, sizeof(Address), 1, f);
859
860       if (1 != rc) 
861          SER_ERR("fwrite");
862    }
863    else {
864       rc = fread(&param, sizeof(Address), 1, f);
865
866       if (1 != rc) 
867          SER_ERR("fread");
868    }
869
870    if (noisy)
871       fprintf(stderr, "%s[%d]:  %sserialize %s=%lx\n", FILE__, __LINE__,
872             iomode_ == sd_serialize ? "" : "de", 
873             tag ? tag : "no-tag", param);
874 }
875
876 void SerDesBin::translate(const char * &param, int bufsize, const char *tag)
877 {
878    //  string output format is
879    //  [1]  length of string
880    //  [2]  string data
881    int rc, len;
882    if (iomode_ == sd_serialize) 
883    {
884       len = strlen(param);
885
886       rc = fwrite( &len, sizeof(int), 1, f);
887
888       if (1 != rc) 
889          SER_ERR("fwrite");
890
891       rc = fwrite(param, sizeof(char), len, f);
892
893       if (len != rc) 
894          SER_ERR("fwrite");
895    }
896    else 
897    {
898       rc = fread(&len, sizeof(int), 1, f);
899
900       if (1 != rc)  
901       {
902          fprintf(stderr, "%s[%d]:  fread, got %d not 1: %s\n", FILE__, __LINE__, rc,  strerror(errno));
903          SER_ERR("fread");
904       }
905
906       if (len > bufsize) 
907       {
908          fprintf(stderr, "%s[%d]:  insufficient buffer\n", FILE__, __LINE__);
909          char msg[128];
910          sprintf(msg, "not enough space in string buffer, %d needed", len);
911          SER_ERR("msg");
912       }
913
914       if (len <= 0) 
915       {
916          fprintf(stderr, "%s[%d]:  bad bufsize %d\n", FILE__, __LINE__, len);
917          char msg[128];
918          sprintf(msg, "bad bufsize, %d ", len);
919          SER_ERR("msg");
920       }
921
922       char *l_ptr = const_cast<char *> (param);
923       rc = fread(l_ptr, sizeof(char), len, f);
924
925       if (len != rc) 
926       {
927          fprintf(stderr, "%s[%d]:  fread, got %d not %d: %s\n", FILE__, __LINE__, rc, len, strerror(errno));
928          SER_ERR("fread");
929       }
930
931       l_ptr[len] = '\0';
932    }
933
934    if (noisy)
935       fprintf(stderr, "%s[%d]:  %sserialize %s=%s\n", FILE__, __LINE__,
936             iomode_ == sd_serialize ? "" : "de", 
937             tag ? tag : "no-tag", param);
938 }
939
940 void SerDesBin::translate(char * &param, int bufsize, const char *tag)
941 {
942    const char * p = const_cast<const char *>(param);
943    translate(p, bufsize, tag);
944    param = const_cast<char *>(p);
945 }
946
947 void SerDesBin::translate(std::string &param, const char *tag)
948 {
949    if (iomode_ == sd_serialize) 
950    {
951       const char *cstr = param.c_str();
952       translate(cstr, 0, tag);
953    }
954    else 
955    {
956       char buf[2048];
957       const char *buf2 = buf;
958       translate(buf2, 2048, tag);
959       param = std::string(buf2);
960    }
961    if ((iomode_ == sd_deserialize) ||strstr(param.c_str(), "file")) 
962    {
963       fprintf(stderr, "%s[%d]:  %sserializing string %s--%s, len = %lu\n", 
964             FILE__, __LINE__, (iomode_ == sd_serialize) ? "" : "de", tag ? tag : "unnamed",
965               param.c_str(), (unsigned long) param.length());
966    }
967 }
968
969 void SerDesBin::translate(std::vector<std::string> &param, const char *tag, const char * elem_tag)
970 {
971    //  string list output format is
972    //  [1]  length of list, n
973    //  [2]  <n> strings
974
975    unsigned int nelem = param.size();
976    translate(nelem, tag);
977
978    if (iomode_ == sd_serialize) 
979    {
980       for (unsigned int i = 0; i < nelem; ++i) 
981       {
982          translate(param[i], elem_tag);
983       }
984    }
985    else 
986    {
987       param.resize(nelem);
988       for (unsigned int i = 0; i < nelem; ++i) 
989       {
990          param[i] = "";
991          translate(param[i], elem_tag);
992       }
993    }
994 }
995
996 AnnotatableBase *SerDesBin::findAnnotatee(void *id) 
997 {
998    Address id_a = (Address) id;
999    dyn_hash_map<Address, AnnotatableBase *>::iterator iter;
1000    iter = annotatable_id_map.find(id_a);
1001    if (iter == annotatable_id_map.end()) 
1002    {
1003       fprintf(stderr, "%s[%d]:  no parent for annotation\n", FILE__, __LINE__);
1004       return NULL;
1005    }
1006    
1007    return iter->second;
1008 }
1009
1010 bool sb_is_input(SerializerBase *sb) 
1011 {
1012    return  (sb->iomode() == sd_deserialize);
1013 }
1014
1015 bool sb_is_output(SerializerBase *sb) 
1016 {
1017    return  (sb->iomode() == sd_serialize);
1018 }
1019
1020 SerializerBase::SerializerBase(const char *name_, 
1021       std::string filename, 
1022       iomode_t dir, 
1023       bool verbose)  :
1024    serializer_name(std::string(name_)) 
1025 {
1026    sf = new SerFile(filename, dir, verbose);
1027    assert(sf);
1028    sd = sf->getSD();
1029    assert(sd);
1030 }
1031
1032 SerializerBase *SerializerBase::getSerializer(std::string subsystem, std::string fname)
1033 {
1034    dyn_hash_map<std::string, subsystem_serializers_t>::iterator ssiter; 
1035    ssiter = all_serializers.find(subsystem);
1036
1037    if (ssiter == all_serializers.end()) 
1038    {
1039       fprintf(stderr, "%s[%d]:  no serializer for subsystem %s\n", FILE__, __LINE__, subsystem.c_str());
1040       return NULL;
1041    }
1042
1043    subsystem_serializers_t &subsys_map = ssiter->second;
1044
1045    dyn_hash_map<std::string, SerializerBase *>::iterator sbiter;
1046    sbiter = subsys_map.find(fname);
1047    if (sbiter == subsys_map.end()) 
1048    {
1049       fprintf(stderr, "%s[%d]:  no serializer for filename %s\n", FILE__, __LINE__, fname.c_str());
1050       return NULL;
1051    }
1052
1053    SerializerBase *sb =  sbiter->second;
1054    if (!sb) 
1055    {
1056       fprintf(stderr, "%s[%d]:  ERROR:  NULL serializer\n", FILE__, __LINE__);
1057       return NULL;
1058    }
1059
1060    return sb;
1061 }
1062
1063 bool SerializerBase::addSerializer(std::string subsystem, std::string fname, SerializerBase *sb)
1064 {
1065    subsystem_serializers_t ss_serializers;
1066    dyn_hash_map<std::string, subsystem_serializers_t>::iterator ssiter; 
1067    ssiter =  all_serializers.find(subsystem);
1068
1069    if (ssiter == all_serializers.end()) 
1070    {
1071       //  make an entry 
1072       all_serializers[subsystem] = ss_serializers;
1073    }
1074
1075    ss_serializers = all_serializers[subsystem];
1076
1077    dyn_hash_map<std::string, SerializerBase *>::iterator sbiter;
1078    sbiter = ss_serializers.find(fname);
1079    if (sbiter != ss_serializers.end()) 
1080    {
1081       fprintf(stderr, "%s[%d]:  already have serializer for filename %s\n", FILE__, __LINE__, fname.c_str());
1082       return false;
1083    }
1084
1085    //  add serializer to map since it does not exist there already
1086
1087    ss_serializers[fname] = sb;
1088    return true;
1089 }
1090
1091 iomode_t SerializerBase::iomode()
1092 {
1093    if (sd) 
1094    {
1095       return sd->iomode();
1096    }
1097
1098    fprintf(stderr, "%s[%d]:  no sd for iomode query\n", FILE__, __LINE__);
1099    return sd_serialize;
1100 }
1101
1102 void SerializerBase::vector_start(unsigned int &size, const char *tag) 
1103 {
1104    getSD().vector_start(size, tag);
1105 }
1106
1107
1108 void SerializerBase::vector_end() 
1109 {
1110    getSD().vector_end();
1111 }
1112
1113 void SerializerBase::hash_map_start(unsigned int &size, const char *tag) 
1114 {
1115    getSD().hash_map_start(size, tag);
1116 }
1117
1118 void SerializerBase::hash_map_end() 
1119 {
1120    getSD().hash_map_end();
1121 }
1122
1123 void SerializerBase::translate_base(short &v, const char *&t)
1124 {
1125    getSD().translate(v, t);
1126 }
1127 void SerializerBase::translate_base(bool &v, const char *&t)
1128 {
1129    getSD().translate(v, t);
1130 }
1131 void SerializerBase::translate_base(char &v, const char *&t)
1132 {
1133    getSD().translate(v, t);
1134 }
1135 void SerializerBase::translate_base(int &v, const char *&t)
1136 {
1137    getSD().translate(v, t);
1138 }
1139 void SerializerBase::translate_base(unsigned int &v, const char *&t)
1140 {
1141    getSD().translate(v, t);
1142 }
1143 void SerializerBase::translate_base(long &v, const char *&t)
1144 {
1145    getSD().translate(v, t);
1146 }
1147 void SerializerBase::translate_base(unsigned long &v, const char *&t)
1148 {
1149    getSD().translate(v, t);
1150 }
1151 void SerializerBase::translate_base(float &v, const char *&t)
1152 {
1153    getSD().translate(v, t);
1154 }
1155 void SerializerBase::translate_base(double &v, const char *&t)
1156 {
1157    getSD().translate(v, t);
1158 }
1159 void SerializerBase::translate_base(const char *&v, int bufsize, const char *&t)
1160 {
1161    getSD().translate(v, bufsize, t);
1162 }
1163 void SerializerBase::translate_base(char *&v, int bufsize, const char *&t)
1164 {
1165    getSD().translate(v, bufsize, t);
1166 }
1167
1168 void SerializerBase::translate_base(std::string &v, const char *t)
1169 {
1170    getSD().translate(v, t);
1171 }
1172
1173 bool isOutput(SerializerBase *ser)
1174 {
1175    return (ser->iomode() == sd_serialize);
1176 }
1177
1178 bool isBinary(SerializerBase *ser)
1179 {
1180    SerializerBin *sb = dynamic_cast<SerializerBin *>(ser);
1181    return (sb != NULL);
1182 }
1183