• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nasa / trick / 30556442809

30 Jul 2026 03:23PM UTC coverage: 56.125% (-0.002%) from 56.127%
30556442809

push

github

web-flow
Add a TMM all that returns the success or failure status of a performed checkpoint restore. (#2167)

* Add a TMM all that returns the success of failure statue of a performed checkpoint restore..

* clang-format

* clang-format

* Changed the return type from int to bool :-)

* clang-format

* clang-format

3 of 11 new or added lines in 4 files covered. (27.27%)

14693 of 26179 relevant lines covered (56.13%)

461983.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

67.82
/trick_source/sim_services/CheckPointAgent/ClassicCheckPointAgent.cpp
1
#include "trick/ClassicCheckPointAgent.hh"
2

3
#include "trick/AttributesUtils.hh"
4
#include "trick/ChkPtParseContext.hh"
5
#include "trick/MemoryManager.hh"
6
#include "trick/bitfield_proto.h"
7
#include "trick/io_alloc.h"
8
#include "trick/message_proto.h"
9
#include "trick/message_type.h"
10
#include "trick/parameter_types.h"
11
#include "trick/wcs_ext.h"
12

13
#include <iomanip>
14
#include <iostream>
15
#include <math.h>
16
#include <sstream>
17
#include <stdlib.h>
18
#include <string.h>
19
#include <string>
20

21
const int Trick::ClassicCheckPointAgent::array_elements_per_line[TRICK_NUMBER_OF_TYPES] = {
22
     5, /** TRICK_VOID (for pointers) */
23
    20, /** TRICK_CHARACTER */
24
    20, /** TRICK_UNSIGNED_CHARACTER */
25
     1, /** TRICK_STRING */
26
    10, /** TRICK_SHORT */
27
    10, /** TRICK_UNSIGNED_SHORT */
28
     5, /** TRICK_INTEGER */
29
     5, /** TRICK_UNSIGNED_INTEGER */
30
     5, /** TRICK_LONG */
31
     5, /** TRICK_UNSIGNED_LONG */
32
     5, /** TRICK_FLOAT */
33
     5, /** TRICK_DOUBLE */
34
     5, /** TRICK_BITFIELD */
35
     5, /** TRICK_UNSIGNED_BITFIELD */
36
     5, /** TRICK_LONG_LONG */
37
     5, /** TRICK_UNSIGNED_LONG_LONG */
38
     5, /** TRICK_FILE_PTR */
39
    10, /** TRICK_BOOLEAN */
40
    10, /** TRICK_WCHAR */
41
     1, /** TRICK_WSTRING */
42
     5, /** TRICK_VOID_PTR */
43
    10, /** TRICK_ENUMERATED */
44
     5, /** TRICK_STRUCTURED (for pointers) */
45
     5, /** TRICK_OPAQUE_TYPE */
46
     1  /** TRICK_STL */
47
};
48

49
static constexpr size_t REFNAME_MAXSIZE = 256;
50

51
// MEMBER FUNCTION
52
Trick::ClassicCheckPointAgent::ClassicCheckPointAgent( Trick::MemoryManager *MM) {
641✔
53

54
   mem_mgr = MM;
641✔
55
   reduced_checkpoint = 1;
641✔
56
   hexfloat_checkpoint = 0;
641✔
57
   debug_level = 0;
641✔
58
}
641✔
59

60
// MEMBER FUNCTION
61
Trick::ClassicCheckPointAgent::~ClassicCheckPointAgent() { }
1,280✔
62

63
// MEMBER FUNCTION
64
bool Trick::ClassicCheckPointAgent::input_perm_check(ATTRIBUTES * attr) {
134,844✔
65
    return (attr->io & TRICK_CHKPNT_INPUT) ;
134,844✔
66
}
67

68
bool Trick::ClassicCheckPointAgent::output_perm_check(ATTRIBUTES * attr) {
182,047✔
69
    return (attr->io & TRICK_CHKPNT_OUTPUT) ;
182,047✔
70
}
71

72
// MEMBER FUNCTION
73
std::string Trick::ClassicCheckPointAgent::left_side_name() {
62,348✔
74

75
    std::string name ;
62,348✔
76
    int ii;
77
    int n_elements = leftside_stack.size();
62,348✔
78

79
    for (ii = 0; ii < n_elements ; ii++) {
241,654✔
80

81
        VarNameElement & element = leftside_stack[ii];
179,306✔
82

83
        switch( element.type) {
179,306✔
84

85
            case BASE_NAME: {
62,348✔
86
                name = element.name;
62,348✔
87
            } break;
62,348✔
88

89
            case ELEM_NAME: {
67,143✔
90
                name += '.' + element.name;
67,143✔
91
            } break;
67,143✔
92

93
            case ARRAY_INDEX: {
49,815✔
94
                std::stringstream index_string;
49,815✔
95
                index_string << element.index;
49,815✔
96
                name += '[';
49,815✔
97
                name += index_string.str();
49,815✔
98
                name += ']';
49,815✔
99
            } break;
49,815✔
100

101
            default: {
×
102
                message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Left side name-stack appears to be corrupted.\n") ;
×
103
            }
104
        }
105
    }
106
    return( name);
62,348✔
107
}
×
108

109
// MEMBER FUNCTION
110
void Trick::ClassicCheckPointAgent::write_decl(std::ostream& chkpnt_os, ALLOC_INFO *info) {
2,843✔
111

112
    const char *type_spec;
113

114
    // Safety check for NULL info pointer or NULL name
115
    if (info == NULL || info->name == NULL) {
2,843✔
116
        return;
120✔
117
    }
118

119
    type_spec = trickTypeCharString(info->type, info->user_type_name);
2,723✔
120

121
    if (info->stcl == TRICK_EXTERN) {
2,723✔
122
        chkpnt_os << "// extern ";
×
123
    }
124

125
    if ( info->num_index == 0 ) {
2,723✔
126

127
        chkpnt_os << type_spec << " " << info->name << ";\n";
101✔
128

129
    } else if ((info->num_index > 0) && (info->num_index <= TRICK_MAX_INDEX)) {
2,622✔
130
        int ii;
131

132
        chkpnt_os << type_spec;
2,622✔
133

134
        ii = info->num_index-1;
2,622✔
135
        while ((ii >= 0) && (info->index[ii] == 0)) {
2,735✔
136
            chkpnt_os << "*";
113✔
137
            ii --;
113✔
138
        }
139

140
        chkpnt_os << " " << info->name ;
2,622✔
141

142
        ii = 0;
2,622✔
143
        while ((ii < info->num_index) && (info->index[ii] != 0)) {
5,243✔
144
            chkpnt_os << "[" << info->index[ii] << "]" ;
2,621✔
145
            ii ++;
2,621✔
146
        }
147
          chkpnt_os << ";" << std::endl;
2,622✔
148

149
    } else {
150
        // ERROR - num_index cant be negative.
151
    }
152
}
153

154
// STATIC FUNCTION
155
/*
156
   Given an address, that is within the bounds of a composite
157
   object (i.e., a struct or class instance), store the corresponding sub-name
158
   in reference_name buffer and return.
159

160
   A return value of 1 indicates an error occured. A return value of 0 indicates
161
   success.
162

163
   The following BNF production describes a valid sub-reference:
164

165
   <sub_reference> --> ""
166
                     | "+" + <offset>
167
                     | "[" + <index>+ "]" + <sub_reference>
168
                     | "." + <member_name> + <sub_reference>
169

170
   <offset> is an integer. It is the the reference offset minus the offset of
171
   the last data member.
172
   <index> is an integer. It is an array index.
173
   <member_name> is a name of a member of the given composite type.
174
*/
175

176
static int getCompositeSubReference(
895✔
177
    void* reference_address, /* Address we are looking for */
178
    ATTRIBUTES** left_type, /* Attributes of type we are looking for */
179
    void* structure_address, /* Address of struct we are in */
180
    ATTRIBUTES* A, /* Attributes of current struct we are in */
181
    char* reference_name /* destination buffer of composite subreference */
182
)
183
{
184
    char* rAddr = (char*)reference_address;
895✔
185
    char* sAddr = (char*)structure_address;
895✔
186

187
    // Validate addresses before computing offset (to avoid unsigned underflow)
188
    if (rAddr < sAddr)
895✔
189
    {
190
        message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Address to find is less than struct address.\\n");
×
191
        return 1;
×
192
    }
193

194
    size_t referenceOffset = (size_t)rAddr - (size_t)sAddr;
895✔
195

196
    Trick::AttributesUtils::TraversalResult traversalResult;
895✔
197
    int ret = Trick::AttributesUtils::traverse_for_offset(referenceOffset, A, traversalResult);
895✔
198

199
    if (ret != 0)
895✔
200
    {
201
        return 1; // Error
×
202
    }
203

204
    // Find the structure member that corresponds to the reference address.
205
    // If name is empty, we have failed.
206

207
    /******If failed to find member, set reference_name to offset only and return ****/
208
    if (traversalResult.is_in_anonymous_member)
895✔
209
    {
210
        if (referenceOffset == 0)
730✔
211
        {
212
            reference_name[0] = '\0';
720✔
213
        }
214
        else
215
        {
216
            snprintf(reference_name, REFNAME_MAXSIZE, " + %zu", referenceOffset);
10✔
217
        }
218
        return 0;
730✔
219
    }
220

221
    /******************************************************************************/
222

223
    ATTRIBUTES* Ai = traversalResult.found_attr;
165✔
224

225
    /* We found a member corresponding to the reference address, so print it's name. */
226
    snprintf(reference_name, REFNAME_MAXSIZE, ".%s", Ai->name);
165✔
227

228
    // If it's a primitive type with computed array indices
229
    if (Ai->type != TRICK_STRUCTURED && traversalResult.num_computed_indices > 0)
165✔
230
    {
231
        // Append array indices
232
        for (int j = 0; j < traversalResult.num_computed_indices; j++)
×
233
        {
234
            size_t len = strlen(reference_name);
×
235
            size_t rem = REFNAME_MAXSIZE - len;
×
236
            snprintf(&reference_name[len], rem, "[%d]", traversalResult.array_indices[j]);
×
237
        }
238
        return 0;
×
239
    }
240

241
    /******** TRICK_STRUCTURED ****************************************************/
242
    /* if it is a reference, do nothing and return */
243
    if (Ai->type == TRICK_STRUCTURED && (Ai->mods & 1) == 1)
165✔
244
    {
245
        return 0;
1✔
246
    }
247

248
    /* if member is an unarrayed struct, continue to call getCompositeSubReference.*/
249
    if (Ai->type == TRICK_STRUCTURED && Ai->num_index == 0)
164✔
250
    {
251
        /* if left_type specifies the current member, stop here */
252
        if ((left_type != NULL) && (*left_type != NULL) && (Ai->attr == (*left_type)->attr))
147✔
253
        {
254
            return 0;
×
255
        }
256

257
        char buf[REFNAME_MAXSIZE];
258
        ret = getCompositeSubReference(rAddr, left_type, sAddr + Ai->offset, (ATTRIBUTES*)Ai->attr, buf);
147✔
259

260
        if (ret == 0)
147✔
261
        {
262
            size_t len = strlen(reference_name);
147✔
263
            size_t rem = REFNAME_MAXSIZE - len;
147✔
264
            snprintf(&reference_name[len], rem, "%s", buf);
147✔
265
        }
266
        return ret;
147✔
267
    }
268

269
    /*** Member is an arrayed struct *********************************************/
270

271
    // If it's a structured type with array indices
272
    if (Ai->type == TRICK_STRUCTURED && traversalResult.num_computed_indices > 0)
17✔
273
    {
274
        // Append array indices
275
        for (int j = 0; j < traversalResult.num_computed_indices; j++)
3✔
276
        {
277
            size_t len = strlen(reference_name);
2✔
278
            size_t rem = REFNAME_MAXSIZE - len;
2✔
279
            snprintf(&reference_name[len], rem, "[%d]", traversalResult.array_indices[j]);
2✔
280
        }
281

282
        /* if left_type specifies the current member, stop here */
283
        if (left_type != NULL && *left_type != NULL && Ai->attr == (*left_type)->attr)
1✔
284
        {
285
            return 0;
×
286
        }
287

288
        /**** Go find the subreference for the arrayed struct member and append *********/
289

290
        // Recurse into the array element
291
        char buf[REFNAME_MAXSIZE];
292
        ret = getCompositeSubReference(rAddr, left_type, sAddr + Ai->offset + traversalResult.offset_from_found_attr,
2✔
293
            (ATTRIBUTES*)Ai->attr, buf);
1✔
294

295
        if (ret == 0)
1✔
296
        {
297
            size_t len = strlen(reference_name);
1✔
298
            size_t rem = REFNAME_MAXSIZE - len;
1✔
299
            snprintf(&reference_name[len], rem, "%s", buf);
1✔
300
        }
301
        return ret;
1✔
302
    }
303

304
    return 0;
16✔
305
}
306

307
// MEMBER FUNCTION
308
// Get the fully qualified varible name of the Allocation, given the address.
309

310
std::string Trick::ClassicCheckPointAgent::get_var_name( void* addr,
747✔
311
                                                         ATTRIBUTES* A,
312
                                                         void* struct_addr,
313
                                                         std::string name,
314
                                                         ATTRIBUTES** left_type) {
315
    char reference_name[REFNAME_MAXSIZE];
316
    int ret;
317
    std::string var_name;
747✔
318

319
    var_name = name;
747✔
320
    ret = getCompositeSubReference( addr, left_type, struct_addr, A, reference_name );
747✔
321

322
    if (ret == 0) {
747✔
323
        var_name += reference_name;
747✔
324
    } else {
325
          std::stringstream ss;
×
326
          ss << "Checkpoint Agent ERROR: Unable to create a subreference of variable \"" << name << "\"."
×
327
             << std::endl;
×
328
          message_publish(MSG_ERROR, ss.str().c_str() );
×
329
    }
×
330
    return (var_name);
1,494✔
331
}
×
332

333
// MEMBER FUNCTION
334
int Trick::ClassicCheckPointAgent::restore( std::istream* checkpoint_stream) {
24✔
335

336
    ChkPtParseContext* context = new ChkPtParseContext( mem_mgr, checkpoint_stream);
24✔
337
    int status = 0;
24✔
338

339
    if ( CCP_parse( context)) {
24✔
340
        status = 1;
×
341
    } else if ((context->bad_declaration_count > 0) ||
24✔
342
               (context->bad_assignment_count > 0)) {
24✔
343
        std::stringstream ss;
×
344
        ss << "Checkpoint Agent ERROR: " << context->bad_declaration_count << " invalid declaration(s) "
×
345
           << "and " << context->bad_assignment_count << " invalid assignment(s)."
×
346
           << std::endl;
×
347
        message_publish(MSG_ERROR, ss.str().c_str() );
×
348
        status = 1;
×
349
    }
×
350

351
    if (status) {
24✔
352
        std::stringstream ss;
×
353
        ss << "Checkpoint Agent ERROR: Checkpoint restore failed."
×
354
           << std::endl;
×
355
        message_publish(MSG_INFO, ss.str().c_str() );
×
NEW
356
        mem_mgr->set_checkpoint_restore_state(false);
×
NEW
357
    }
×
358
    else
359
    {
360
        mem_mgr->set_checkpoint_restore_state(true);
24✔
361
    }
362
    delete context ;
24✔
363
    return (status);
24✔
364
}
365

366
// MEMBER FUNCTION
367
int Trick::ClassicCheckPointAgent::is_nil_valued( void* address,
72,015✔
368
                                                  ATTRIBUTES* attr,
369
                                                  int curr_dim,
370
                                                  int offset
371
                                                ) {
372

373
    char* test_addr;
374
    int remaining_dimensions = attr->num_index - curr_dim;
72,015✔
375

376
    /** @par Detailed Description: */
377

378
    /** @par
379
        If we're referencing a singleton then calculate the test-address
380
        from the (base) address, the offset and the data-type. Then
381
        test that calculated address (with the given type) for nil.
382
        If it's nil return 1, otherwise return 0.
383
     */
384
    if (remaining_dimensions ==0) {
72,015✔
385

386
        switch (attr->type) {
67,616✔
387
           case TRICK_CHARACTER :
7,280✔
388
           case TRICK_UNSIGNED_CHARACTER :
389
               test_addr = (char*)address + offset * sizeof(char);
7,280✔
390
               if (*(char*)test_addr == '\0') return(1);
7,280✔
391
               break;
53✔
392
           case TRICK_BOOLEAN:
14,437✔
393
               test_addr = (char*)address + offset * sizeof(bool);
14,437✔
394
               if (*(bool*)test_addr == false) return(1);
14,437✔
395
               break;
2,873✔
396
           case TRICK_WCHAR :
×
397
               test_addr = (char*)address + offset * sizeof(wchar_t);
×
398
               if (*(wchar_t*)test_addr == 0) return(1);
×
399
               break;
×
400
           case TRICK_SHORT :
2,379✔
401
           case TRICK_UNSIGNED_SHORT :
402
               test_addr = (char*)address + offset * sizeof(short);
2,379✔
403
               if (*(short*)test_addr == 0) return(1);
2,379✔
404
               break;
2,001✔
405
           case TRICK_INTEGER :
13,933✔
406
           case TRICK_UNSIGNED_INTEGER :
407
               test_addr = (char*)address + offset * sizeof(int);
13,933✔
408
               if (*(int*)test_addr == 0) return(1);
13,933✔
409
               break;
7,364✔
410
           case TRICK_ENUMERATED :
408✔
411
               if ((size_t)attr->size == sizeof(int)) {
408✔
412
                   test_addr = (char*)address + offset * sizeof(int);
404✔
413
                   if (*(int*)test_addr == 0) return(1);
404✔
414
               } else if ((size_t)attr->size == sizeof(short)) {
4✔
415
                   test_addr = (char*)address + offset * sizeof(short);
2✔
416
                   if (*(short*)test_addr == 0) return(1);
2✔
417
               } else if ((size_t)attr->size == sizeof(char)) {
2✔
418
                   test_addr = (char*)address + offset * sizeof(char);
2✔
419
                   if (*(char*)test_addr == 0) return(1);
2✔
420
               } else {
421
                   return(-1);
×
422
               }
423
               break;
90✔
424
           case TRICK_LONG :
103✔
425
           case TRICK_UNSIGNED_LONG :
426
               test_addr = (char*)address + offset * sizeof(long);
103✔
427
               if (*(long*)test_addr == 0) return(1);
103✔
428
               break;
49✔
429
           case TRICK_FLOAT :
2✔
430
               test_addr = (char*)address + offset * sizeof(float);
2✔
431
               if (fpclassify( *(float*)test_addr) == FP_ZERO) return(1);
2✔
432
               break;
2✔
433
           case TRICK_DOUBLE :
7,969✔
434
               test_addr = (char*)address + offset * sizeof(double);
7,969✔
435
               if (fpclassify( *(double*)test_addr) == FP_ZERO) return(1);
7,969✔
436
               break;
5,089✔
437
           case TRICK_LONG_LONG :
9,967✔
438
           case TRICK_UNSIGNED_LONG_LONG :
439
               test_addr = (char*)address + offset * sizeof(long long);
9,967✔
440
               if (*(long long*)test_addr == 0) return(1);
9,967✔
441
               break;
914✔
442
           case TRICK_BITFIELD :
×
443
           case TRICK_UNSIGNED_BITFIELD :
444
               test_addr = (char*)address + offset * (size_t)attr->size;
×
445
               if (attr->size == sizeof(int)) {
×
446
                   if (*(int*)test_addr == 0) return(1);
×
447
               } else if (attr->size == sizeof(short)) {
×
448
                   if (*(short*)test_addr == 0) return(1);
×
449
               } else if (attr->size == sizeof(char)) {
×
450
                   if (*(char*)test_addr == 0) return(1);
×
451
               } else {
452
                   message_publish(MSG_ERROR, "Checkpoint Agent INTERNAL ERROR:\n"
×
453
                                              "Unhandled bitfield struct size (%d) in bitfield assignment.\n", attr->size) ;
454
                   return(-1);
×
455
               }
456
               break;
×
457
           case TRICK_FILE_PTR :
×
458
               // FIXME
459
               return(0);
×
460
               break;
461
           case TRICK_STRING :
8,597✔
462
               test_addr = (char*)address + offset * sizeof(void*);
8,597✔
463
               if (*(std::string*)test_addr == "") return(1);
8,597✔
464
               break;
8,065✔
465
           case TRICK_WSTRING :
×
466
               test_addr = (char*)address + offset * sizeof(std::wstring);
×
467
               if (*(std::wstring*)test_addr == L"") return(1);
×
468
               break;
×
469
           case TRICK_STL :
2,541✔
470
               // Can't test properly, always return 0 to indicate the STL is not empty.
471
               return(0);
2,541✔
472
               break;
473
           default :
×
474
               message_publish(MSG_ERROR, "Checkpoint Agent file %s: Unhandled Type (%d).\n", __FILE__, attr->type) ;
×
475
               return(-1);
×
476
               break;
477
        }
478
        return(0);
26,500✔
479

480
    /** @par
481
        If on the otherhand we are referencing an array, then we must consider two cases.
482
     */
483
    } else if (remaining_dimensions > 0) {
4,399✔
484
       int curr_dim_size;
485
       curr_dim_size = attr->index[curr_dim].size ;
4,399✔
486

487
       /**  @par
488
            If the array is unconstrained (i.e., it's a pointer) then we just need to check
489
            whether the pointer is NULL.
490
        */
491
       if ( curr_dim_size == 0) {
4,399✔
492
           test_addr = ((char*)address) + (offset*sizeof(void *));
1,846✔
493
           if (*(char**)test_addr == NULL) return(1);
1,846✔
494

495
       /** @par
496
           If the array (at this dimension) is constrained (i.e., it's a fixed array )
497
           then it is nil if and only if each of it's sub-elements (at the next dimension,
498
           which can themselves be arrays) are nil. So, for each of the elements in current
499
           dimension, we recursively call is_nil_valued() on each of the sub-elements to
500
           find out whether this array is nil valued and return the result.
501
           */
502
       } else {
503
           int ii;
504
           int zerotest;
505

506
           for (ii=0; ii < curr_dim_size; ii++) {
9,752✔
507
               zerotest = is_nil_valued( address, attr, curr_dim+1, offset*curr_dim_size+ii);
9,667✔
508
               if (!(zerotest == 1)) return(zerotest);
9,667✔
509
           }
510
           return(1);
85✔
511
       }
512

513
    } else {
514
        return(-1);
×
515
    }
516
    return(0);
905✔
517
}
518

519
// STATIC FUNCTION
520
static void write_quoted_str( std::ostream& os, const char* s) {
8,547✔
521
    int ii;
522
    int len = strlen(s);
8,547✔
523
    os << "\"" ;
8,547✔
524
    for (ii=0 ; ii<len ; ii++) {
148,947✔
525
        switch ((s)[ii]) {
140,400✔
526
        case '\n': os << "\\n"; break;
54✔
527
        case '\t': os << "\\t"; break;
×
528
        case '\b': os << "\\b"; break;
×
529
        case '\"': os << "\\\""; break;
44✔
530
        default  : os << s[ii] ; break;
140,302✔
531
        }
532
    }
533
    os << "\"" ;
8,547✔
534
}
8,547✔
535

536
void Trick::ClassicCheckPointAgent::write_singleton( std::ostream& chkpnt_os, void* address, ATTRIBUTES* attr, int offset ) {
28,151✔
537

538
    void* src_addr;
539

540
    switch(attr->type) {
28,151✔
541
        case TRICK_VOID:
×
542
            chkpnt_os << std::endl << "// ERROR - VOID data type cannot be checkpointed." << std::endl;
×
543
            message_publish(MSG_ERROR, "Checkpoint Agent ERROR: VOID data type cannot be checkpointed.\n") ;
×
544
        break;
×
545
        case TRICK_UNSIGNED_CHARACTER:
1✔
546
            src_addr = (char*)address + offset * sizeof(unsigned char);
1✔
547
            chkpnt_os << std::dec << (int)*(unsigned char*)src_addr ;
1✔
548
        break;
1✔
549
        case TRICK_BOOLEAN:
2,874✔
550
            src_addr = (char*)address + offset * sizeof(bool);
2,874✔
551
            if (*(bool*)src_addr) {
2,874✔
552
                chkpnt_os << "true" ;
2,873✔
553
            } else {
554
                chkpnt_os << "false" ;
1✔
555
            }
556
        break;
2,874✔
557
        case TRICK_CHARACTER:
1,121✔
558
            src_addr = (char*)address + offset * sizeof(char);
1,121✔
559
            if (isprint( *(char*)src_addr) ) {
1,121✔
560
                chkpnt_os << "'" << *(char*)src_addr << "'" ;
682✔
561
            } else {
562
                unsigned int ch = *(unsigned char*)src_addr;
439✔
563
                  chkpnt_os << "'\\x" << std::hex << ch << "'" ;
439✔
564
            }
565
        break;
1,121✔
566
        case TRICK_WCHAR: {
×
567
            src_addr = (char*)address + offset * sizeof(wchar_t);
×
568
            char buff[16] = {0};
×
569
            wctomb(buff,*(wchar_t*)src_addr);
×
570
            chkpnt_os << std::dec << buff;
×
571
            }
572
            break;
×
573
        case TRICK_SHORT:
8✔
574
            src_addr = (char*)address + offset * sizeof(short);
8✔
575
            chkpnt_os << std::dec << *(short*)src_addr;
8✔
576
            break;
8✔
577
        case TRICK_UNSIGNED_SHORT:
1,997✔
578
            src_addr = (char*)address + offset * sizeof(unsigned short);
1,997✔
579
            chkpnt_os << std::dec << *(unsigned short*)src_addr;
1,997✔
580
            break;
1,997✔
581
        case TRICK_ENUMERATED: {
94✔
582
                int ii = 0;
94✔
583
                int found = 0;
94✔
584
                int value;
585
                ENUM_ATTR* enum_attr;
586

587
                if ((size_t)attr->size == sizeof(int)) {
94✔
588
                    src_addr = (char*)address + offset * sizeof(int);
90✔
589
                    value =  *(int*)src_addr;
90✔
590
                } else if ((size_t)attr->size == sizeof(short)) {
4✔
591
                    src_addr = (char*)address + offset * sizeof(short);
2✔
592
                    value =  *(short*)src_addr;
2✔
593
                } else if ((size_t)attr->size == sizeof(char)) {
2✔
594
                    src_addr = (char*)address + offset * sizeof(char);
2✔
595
                    ENUM_ATTR* eattr = (ENUM_ATTR*)attr->attr;
2✔
596
                    if (eattr != nullptr && (eattr[0].mods & 0x40000000)) {
2✔
597
                        value = (int)(unsigned char)*(char*)src_addr;
1✔
598
                    } else {
599
                        value = (int)*(char*)src_addr;
1✔
600
                    }
601
                } else {
602
                    std::cerr << __FUNCTION__ << ": enumeration size error." << std::endl;
×
603
                    std::cerr.flush();
×
604
                    value = -1;
×
605
                }
606

607
                enum_attr = (ENUM_ATTR*)attr->attr;
94✔
608

609
                while ( !found && (enum_attr[ii].label[0] != '\0')) {
345✔
610
                   if (value == enum_attr[ii].value) {
251✔
611
                       chkpnt_os << enum_attr[ii].label;
94✔
612
                       found = 1;
94✔
613
                   }
614
                   ii++;
251✔
615
                }
616
                if (!found) {
94✔
617
                    chkpnt_os << std::dec << value;
×
618
                }
619

620
            } break;
94✔
621
        case TRICK_INTEGER:
7,380✔
622
            src_addr = (char*)address + offset * sizeof(int);
7,380✔
623
            chkpnt_os << std::dec << *(int*)src_addr;
7,380✔
624
            break;
7,380✔
625
        case TRICK_UNSIGNED_INTEGER:
321✔
626
            src_addr = (char*)address + offset * sizeof(unsigned int);
321✔
627
            chkpnt_os << std::dec << *(unsigned int*)src_addr;
321✔
628
            break;
321✔
629
        case TRICK_LONG:
41✔
630
            src_addr = (char*)address + offset * sizeof(long);
41✔
631
            chkpnt_os << std::dec << *(long*)src_addr;
41✔
632
            break;
41✔
633
        case TRICK_UNSIGNED_LONG:
13✔
634
            src_addr = (char*)address + offset * sizeof(unsigned long);
13✔
635
            chkpnt_os << std::dec << *(unsigned long*)src_addr;
13✔
636
            break;
13✔
637
        case TRICK_FLOAT:
4✔
638
            src_addr = (char*)address + offset * sizeof(float);
4✔
639
            if (fpclassify( *(float*)src_addr) != FP_NAN) {
4✔
640
                if (hexfloat_checkpoint) {
4✔
641
                    double temp_dbl = *(float*)src_addr;
×
642
                    unsigned char* byte_p = (unsigned char*)&temp_dbl;
×
643
                    chkpnt_os << "0g";
×
644
                    for (int ii=sizeof(double)-1 ; ii>= 0 ; ii--) {
×
645
                        chkpnt_os << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)byte_p[ii];
×
646
                    }
647
                } else {
648
                    chkpnt_os << std::setprecision(8) << *(float*)src_addr;
4✔
649
                }
650
            } else {
651
                chkpnt_os << "NAN";
×
652
            }
653
            break;
4✔
654
        case TRICK_DOUBLE:
5,226✔
655
            src_addr = (char*)address + offset * sizeof(double);
5,226✔
656
            if (fpclassify( *(double*)src_addr) != FP_NAN) {
5,226✔
657
                if (hexfloat_checkpoint) {
5,226✔
658
                    double temp_dbl = *(double*)src_addr;
4✔
659
                    unsigned char* byte_p = (unsigned char*)&temp_dbl;
4✔
660
                    chkpnt_os << "0g";
4✔
661
                    for (int ii=sizeof(double)-1 ; ii>= 0 ; ii--) {
36✔
662
                        chkpnt_os << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)byte_p[ii];
32✔
663
                    }
664
                } else {
665
                    chkpnt_os << std::setprecision(16) << *(double*)src_addr;
5,222✔
666
                }
667
            } else {
668
                chkpnt_os << "NAN";
×
669
            }
670
            break;
5,226✔
671
        case TRICK_BITFIELD: {
×
672
                int sbf = 0;
×
673
                src_addr = (char*)address + offset * (size_t)attr->size;
×
674
                if (attr->size == sizeof(int)) {
×
675
                     sbf = extract_bitfield_any( *(int*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
676
                } else if (attr->size == sizeof(short)) {
×
677
                     sbf = extract_bitfield_any( *(short*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
678
                } else if (attr->size == sizeof(char)) {
×
679
                     sbf = extract_bitfield_any( *(char*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
680
                } else {
681
                     message_publish(MSG_ERROR, "Checkpoint Agent INTERNAL ERROR:\n"
×
682
                                                "Unsupported bitfield size (%d) bytes.\n", attr->size) ;
683
                }
684
                chkpnt_os << std::dec << sbf;
×
685
            } break;
×
686
        case TRICK_UNSIGNED_BITFIELD: {
×
687
                int bf = 0;
×
688
                src_addr = (char*)address + offset * (size_t)attr->size;
×
689
                if (attr->size == sizeof(int)) {
×
690
                     bf = extract_unsigned_bitfield_any( *(unsigned int*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
691
                } else if (attr->size == sizeof(short)) {
×
692
                     bf = extract_unsigned_bitfield_any( *(unsigned short*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
693
                } else if (attr->size == sizeof(char)) {
×
694
                     bf = extract_unsigned_bitfield_any( *(unsigned char*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
695
                } else {
696
                     message_publish(MSG_ERROR, "Checkpoint Agent INTERNAL ERROR:\n"
×
697
                                                "Unsupported bitfield size (%d) bytes.\n", attr->size) ;
698
                }
699
                chkpnt_os << std::dec << bf;
×
700
            } break;
×
701
        case TRICK_LONG_LONG:
900✔
702
            src_addr = (char*)address + offset * sizeof(long long);
900✔
703
            chkpnt_os << std::dec << *(long long*)src_addr;
900✔
704
            break;
900✔
705
        case TRICK_UNSIGNED_LONG_LONG:
18✔
706
            src_addr = (char*)address + offset * sizeof(unsigned long long);
18✔
707
            chkpnt_os << std::dec << *(unsigned long long*)src_addr;
18✔
708
            break;
18✔
709
        case  TRICK_FILE_PTR:
×
710
            src_addr = (char*)address + offset * sizeof(void*);
×
711
            chkpnt_os << *(void**)src_addr;
×
712
            break;
×
713
        case TRICK_STRING:
8,153✔
714
            src_addr = (char*)address + offset * sizeof(std::string);
8,153✔
715
            write_quoted_str(chkpnt_os, (*(std::string*)src_addr).c_str());
8,153✔
716
            break;
8,153✔
717
        case TRICK_WSTRING: {
×
718
            src_addr = (char*)address + offset * sizeof(std::wstring);
×
719
            const std::wstring& wstr = *(std::wstring*)src_addr;
×
720
            size_t ncs_len = wcs_to_ncs_len(wstr.c_str()) + 1;
×
721
            char* ncs_buf = new char[ncs_len];
×
722
            wcs_to_ncs(wstr.c_str(), ncs_buf, ncs_len);
×
723
            write_quoted_str(chkpnt_os, ncs_buf);
×
724
            delete[] ncs_buf;
×
725
            break;
×
726
        }
727
        case TRICK_OPAQUE_TYPE:
×
728
            chkpnt_os << std::endl << "// ERROR - OPAQUE data type (" << attr->type_name << ") cannot be checkpointed." << std::endl;
×
729
            message_publish(MSG_ERROR, "Checkpoint Agent ERROR: OPAQUE data type (%s) cannot be checkpointed.\n", attr->type_name) ;
×
730
        break;
×
731
        default:
×
732
            chkpnt_os << "0";
×
733
            message_publish(MSG_ERROR, "Checkpoint Agent file %s: Unhandled Type (%d).\n", __FILE__, attr->type) ;
×
734
            break;
×
735
    }
736
}
28,151✔
737

738
// MEMBER FUNCTION
739
// Get the variable-name associated with the given variable-address and data-type.
740
// If no data-type is specified, (i.e., if attr == NULL), then the name will refer
741
// to the (inner-most) primitive data-type associated with the address.
742

743
// attr and curr_dim together specify the expected data-type.
744
// If (attr == NULL) then type checking can't and won't be performed.
745

746
std::string Trick::ClassicCheckPointAgent::
1,144✔
747
    ref_string_from_ptr( void* pointer, ATTRIBUTES* attr, int curr_dim) {
748

749
    std::string reference_string;
1,144✔
750

751
    if ((attr != NULL) && ((curr_dim >= attr->num_index) || (attr->index[curr_dim].size != 0))) {
1,144✔
752
        message_publish(MSG_ERROR, "Checkpoint Agent ERROR: ref_string_from_ptr called with a non-pointer type.\n") ;
×
753
    }
754

755
    if (pointer == NULL) {
1,144✔
756
        reference_string = "NULL";
×
757
    } else {
758
        ALLOC_INFO *alloc_info;
759

760
        /** Find the allocation that contains the pointer-address. */
761
        alloc_info = mem_mgr->get_alloc_info_of( pointer);
1,144✔
762

763
        if (alloc_info != NULL) {
1,144✔
764
            // Special handling for character strings: prefer string literal format over allocation reference
765
            // The following info for "char *" is for reference purpose:
766
            // curr_dim = 0
767
            // attr.type = TRICK_CHARACTER (base type)
768
            // attr.num_index = 1 (1D array)
769
            // attr.index[0].size = 0 (not static array)
770
            // attr.size = sizeof(char)
771
            // This prevents anonymous allocations from appearing in subsequent checkpoints
772
            if ((attr != NULL) && (attr->type == TRICK_CHARACTER || attr->type == TRICK_UNSIGNED_CHARACTER) && ((curr_dim + 1) == attr->num_index)) {
1,107✔
773
                std::stringstream ss;
101✔
774
                write_quoted_str( ss, (const char*)pointer);
101✔
775
                reference_string = ss.str();
101✔
776
            } else {
101✔
777
                int alloc_elem_size;
778
                int alloc_elem_index;
779
                int misalignment;
780

781
                alloc_elem_size = alloc_info->size;
1,006✔
782
                alloc_elem_index = (int) (((long) pointer - (long) alloc_info->start) / alloc_elem_size);
1,006✔
783
                misalignment = (int) (((long) pointer - (long) alloc_info->start) % alloc_elem_size);
1,006✔
784

785
                // If type-checking AND the type specifiers match AND  the type we're looking for
786
                // is either not structured or if it is, the attr-list that describes the contents
787
                // of the structure is the same.
788

789
                if ( (attr != NULL) && (attr->type == alloc_info->type) &&
1,006✔
790
                     ( (attr->type != TRICK_STRUCTURED) || (attr->attr == alloc_info->attr))) {
852✔
791

792
                int ii;
793
                int n_l_ptrs, n_r_ptrs;
794

795
                // Calculate the number of pointers (asterisks) on the left side of the assignment.
796
                n_l_ptrs = attr->num_index - curr_dim;
258✔
797

798
                // Calculate the number of pointers (asterisks) on the right side of the assignment.
799
                n_r_ptrs = 0;
258✔
800
                for (ii=0 ; ii <alloc_info->num_index ; ii++) {
490✔
801
                    if (alloc_info->index[ii] == 0) n_r_ptrs++;
232✔
802
                }
803

804
                if (n_l_ptrs != (n_r_ptrs + 1)) {
258✔
805
                    reference_string = "NULL /*ERROR: # asterisks disagree.*/";
×
806
                } else {
807
                    if (misalignment == 0) {
258✔
808
                        std::stringstream workss;
258✔
809
                        if (alloc_info->name != NULL) {
258✔
810
                            workss << "&" << alloc_info->name;
258✔
811
                            if (alloc_info->num_index != 0) {
258✔
812
                                workss << "[" << alloc_elem_index << "]";
166✔
813
                            }
814
                            reference_string = workss.str();
258✔
815
                        } else {
816
                            std::stringstream ss;
×
817
                            ss << "Checkpoint Agent ERROR: The name of the allocation at " << alloc_info->start << " is NULL."
×
818
                               << "Therefore, Trick::ClassicCheckPointAgent::ref_string_from_ptr() can't generate a textual reference to it."
×
819
                               << std::endl;
×
820
                            message_publish(MSG_ERROR, ss.str().c_str() );
×
821
                            reference_string = "ERROR - Allocation name is NULL";
×
822
                        }
×
823

824
                    } else {
258✔
825
                        message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Badly aligned pointer.\n"
×
826
                                                   "   It is not aligned with the data object\n"
827
                                                   "   (of the same type) into which it is pointing.\n") ;
828
                        reference_string = "ERROR - Badly aligned pointer";
×
829
                    }
830
                }
831
            } else if (alloc_info->type == TRICK_STRUCTURED) {
1,006✔
832
                // The type specifications don't match, but the right-side is structured,
833
                // so we apparently the matching type is buried in the right hand side structure.
834

835
                if (alloc_info->name != NULL) {
747✔
836
                    std::string rightside;
747✔
837
                    std::stringstream element_name;
747✔
838
                    element_name << "&" << alloc_info->name;
747✔
839
                    if (alloc_info->num_index != 0) {
747✔
840
                        element_name << '[' << alloc_elem_index << ']';
196✔
841
                    }
842
                    rightside = get_var_name( pointer,
747✔
843
                                              alloc_info->attr,
844
                                              (char *) alloc_info->start + (alloc_elem_index * alloc_info->size),
747✔
845
                                              element_name.str(),
1,494✔
846
                                              &attr
847
                                            );
747✔
848
                    reference_string = rightside;
747✔
849
                } else {
747✔
850
                    std::stringstream ss;
×
851
                    ss << "Checkpoint Agent ERROR: The name of the allocation at " << alloc_info->start << " is NULL."
×
852
                       << "Therefore, Trick::ClassicCheckPointAgent::ref_string_from_ptr() can't generate a textual reference to it."
×
853
                       << std::endl;
×
854
                    message_publish(MSG_ERROR, ss.str().c_str() );
×
855
                    reference_string = "ERROR - Allocation name is NULL";
×
856
                }
×
857
            } else { // The type specifications don't match, and the right hand side is not structured
858

859
                if (attr != NULL) {
1✔
860
                    const char* left_type_spec  = trickTypeCharString(attr->type, "");
×
861
                    const char* right_type_spec = trickTypeCharString(alloc_info->type, alloc_info->user_type_name);
×
862
                    message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Type mismatch. Type specifications disagree.\n"
×
863
                                               "   The left side type specifier is \"%s\" but the right side is \"%s\".\n",
864
                                    left_type_spec, right_type_spec) ;
865
                    reference_string = "ERROR - Type specifications disagree";
×
866
                } else {
867

868
                    if (misalignment == 0) {
1✔
869
                        std::stringstream workss;
1✔
870

871
                        if (alloc_info->name != NULL) {
1✔
872
                            workss << "&" << alloc_info->name;
1✔
873
                            if (alloc_info->num_index != 0) {
1✔
874
                                workss << "[" << alloc_elem_index << "]";
×
875
                            }
876
                            reference_string = workss.str();
1✔
877
                        } else {
878
                            std::stringstream ss;
×
879
                            ss << "Checkpoint Agent ERROR: The name of the allocation at " << alloc_info->start << " is NULL."
×
880
                               << "Therefore, Trick::ClassicCheckPointAgent::ref_string_from_ptr() can't generate a textual reference to it."
×
881
                               << std::endl;
×
882
                            message_publish(MSG_ERROR, ss.str().c_str() );
×
883
                            reference_string = "ERROR - Allocation name is NULL";
×
884
                        }
×
885

886
                    } else {
1✔
887
                        message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Badly aligned pointer.\n"
×
888
                                                   "   It is not aligned with the data object\n"
889
                                                   "   (of the same type) into which it is pointing.\n") ;
890
                        reference_string = "ERROR - Badly Aligned Pointer";
×
891
                    }
892
                }
893

894
                }
895
            }
896
        } else if ((attr != NULL) && ((curr_dim + 1) == attr->num_index)) {
37✔
897

898
            if (attr->type == TRICK_CHARACTER) {
37✔
899
                std::stringstream ss;
37✔
900
                write_quoted_str( ss, (const char*)pointer);
37✔
901
                reference_string = ss.str();
37✔
902
            } else if (attr->type == TRICK_WCHAR) {
37✔
903
                message_publish(MSG_ERROR, "Checkpoint Agent ERROR: TRICK_WCHAR not fully supported yet.\n") ;
×
904
                reference_string = "ERROR: TRICK_WCHAR not fully supported yet.";
×
905
            } else {
906
                std::string lname = left_side_name();
×
907
                message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Pointer <%p> in \"%s\" is not in Trick managed memory\n"
×
908
                                           "nor is it a character pointer.\n", pointer, lname.c_str()) ;
909
                reference_string = "ERROR - Pointer not in Trick managed memory";
×
910
            }
×
911

912
        } else {
37✔
913
            std::string lname = left_side_name();
×
914
            message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Pointer <%p> in \"%s\" is not in Trick managed memory\n"
×
915
                                       "nor is it a character pointer.\n", pointer, lname.c_str()) ;
916
            reference_string = "ERROR - Pointer not in Trick managed memory";
×
917
        }
×
918
    }
919
    return( reference_string);
1,144✔
920
}
×
921

922
// MEMBER FUNCTION
923
void Trick::ClassicCheckPointAgent::write_rvalue( std::ostream& chkpnt_os, void* address, ATTRIBUTES* attr, int curr_dim, int offset) {
31,869✔
924

925
    // If the variable that we are pointing to is Un-arrayed
926
    if (curr_dim == attr->num_index) {
31,869✔
927

928
        write_singleton( chkpnt_os, address, attr, offset);
28,151✔
929

930
    // If the variable that we are pointing to is Arrayed
931
    } else if (curr_dim < attr->num_index) {
3,718✔
932

933
        // If the variable is a pointer
934
        if (attr->index[curr_dim].size == 0) {
3,718✔
935
            std::string ref_string;
993✔
936

937
            void* pointer = *(void**)((char*)address + offset * sizeof(void*));
993✔
938

939
            ref_string = ref_string_from_ptr( pointer, attr, curr_dim);
993✔
940

941
            chkpnt_os << ref_string.c_str() ;
993✔
942

943
        } else { // Fixed dimension
993✔
944

945
            char* src_addr;
946

947
            // If this is the final, fixed dimension
948
            if (((curr_dim + 1) == attr->num_index) ||
2,725✔
949
                (attr->index[curr_dim + 1].size == 0)) {
49✔
950

951
                int use_quoted_string;
952

953
                // If ALL but the last of the elements of a character array
954
                // "isprintable" AND the last is '\0' then print out the array
955
                // as a quoted string. Otherwise print out each of the characters.
956

957
                use_quoted_string = 1;
2,721✔
958
                if (attr->type == TRICK_CHARACTER) {
2,721✔
959

960
                    int array_len = attr->index[curr_dim].size;
304✔
961
                    int ii = array_len - 1;
304✔
962
                    src_addr = (char*)address + offset * array_len * sizeof(char);
304✔
963
                    if (src_addr[ii] != '\0') {
304✔
964
                        use_quoted_string = 0;
22✔
965
                    }
966
                    ii--;
304✔
967
                    while ( use_quoted_string && (ii >= 0) ) {
1,097✔
968
                        use_quoted_string = isprint( src_addr[ii]);
793✔
969
                        ii--;
793✔
970
                    }
971
                }
972

973

974
                // This is necessary due to https://github.com/nasa/trick/issues/1399
975
                // If there is a string array where the memory is not initialized, the code above
976
                // can incorrectly decide to write it as a quoted string when it should be an
977
                // empty array, causing a segfault when the checkpoint is reloaded.
978
                if (attr->index[curr_dim + 1].size == 0 && ((curr_dim + 1) != attr->num_index)) {
2,721✔
979
                    use_quoted_string = 0;
45✔
980
                } 
981

982

983
                if ((attr->type == TRICK_CHARACTER) && use_quoted_string)  {
2,721✔
984

985
                    write_quoted_str(chkpnt_os, src_addr);
256✔
986

987
                } else {
988

989
                    int ii, jj;
990
                    int array_len;
991

992
                    // Determine the number of array elements we need to print out
993
                    // to get all of the non-zero values.
994

995
                    array_len = attr->index[curr_dim].size ;
2,465✔
996

997
                    chkpnt_os << "\n";
2,465✔
998

999
                    for (ii=0 ; ii < curr_dim+1 ; ii++) {
4,935✔
1000
                        chkpnt_os << "    ";
2,470✔
1001
                    }
1002
                    chkpnt_os << "{";
2,465✔
1003

1004
                    for (ii = 0; ii < array_len ; ii++ ) {
6,668✔
1005

1006
                        if (ii > 0) {
4,203✔
1007
                            chkpnt_os << ", ";
1,738✔
1008

1009
                            // Conditionally line-break and indent.
1010
                            if (( (ii+1) % array_elements_per_line[attr->type]) == 0 ) {
1,738✔
1011
                                // Line-break.
1012
                                chkpnt_os << "\n";
198✔
1013
                                // Indent.
1014
                                for (jj=0 ; jj < curr_dim+1 ; jj++) {
396✔
1015
                                    chkpnt_os << "    ";
198✔
1016
                                }
1017
                                chkpnt_os << " ";
198✔
1018
                            }
1019
                        }
1020
                        write_rvalue( chkpnt_os, address, attr, curr_dim + 1, offset * attr->index[curr_dim].size + ii);
4,203✔
1021
                    }
1022
                    chkpnt_os << "}";
2,465✔
1023

1024
                }
1025

1026
            } else { // Not the final fixed dimension.
2,721✔
1027

1028
                int ii;
1029

1030
                chkpnt_os << "\n";
4✔
1031
                for (ii=0 ; ii < curr_dim+1 ; ii++) {
8✔
1032
                    chkpnt_os << "    ";
4✔
1033
                }
1034
                chkpnt_os << "{";
4✔
1035

1036
                for (ii=0 ; ii< attr->index[curr_dim].size ; ii++) {
265✔
1037
                    if (ii > 0) {
261✔
1038
                        chkpnt_os << ",";
257✔
1039
                    }
1040
                    write_rvalue( chkpnt_os, address, attr, curr_dim + 1, offset * attr->index[curr_dim].size + ii);
261✔
1041
                }
1042

1043
                chkpnt_os << "\n";
4✔
1044

1045
                for (ii=0 ; ii < curr_dim+1 ; ii++) {
8✔
1046
                    chkpnt_os << "    " ;
4✔
1047
                }
1048
                chkpnt_os << "}";
4✔
1049
            }
1050
        }
1051

1052
    } else {
1053
        chkpnt_os << "/*ERROR*/";
×
1054

1055
        message_publish(MSG_ERROR, "Checkpoint Agent ERROR: The specified current dimension \"%d\" is greater\n"
×
1056
                                   "than the number of dimensions specified in the type ATTRIBUTES.\n", curr_dim) ;
1057

1058
        return;
×
1059
    }
1060
}
1061

1062
// MEMBER FUNCTION
1063
// Create an assignment statement.
1064
void Trick::ClassicCheckPointAgent::assign_rvalue(std::ostream& chkpnt_os, void* address, ATTRIBUTES* attr, int curr_dim, int offset) {
62,348✔
1065

1066
    std::string lname = left_side_name();
62,348✔
1067

1068
    if (!output_perm_check(attr)) {
62,348✔
1069
        if (debug_level) {
×
1070
            message_publish(MSG_DEBUG, "Checkpoint Agent INFO: No assignment generated for \"%s\" "
×
1071
                                       "because its io specification does not allow it.\n", lname.c_str()) ;
1072
        }
1073
        return;
×
1074
    }
1075

1076
    if ((reduced_checkpoint && is_nil_valued( (void*)address, attr, curr_dim, offset ) ) ) {
62,348✔
1077
        if (debug_level) {
32,402✔
1078
            message_publish(MSG_DEBUG, "Checkpoint Agent INFO: No assignment generated for \"%s\" "
×
1079
                                       "because its value is nil and the reduced_checkpoint flag is set.\n", lname.c_str()) ;
1080
        }
1081
        return;
32,402✔
1082
    }
1083

1084
    if (debug_level) {
29,946✔
1085
        message_publish(MSG_DEBUG, "Checkpoint Agent INFO: Generating assignment for [%p] %s.\n",(void*)address, lname.c_str()) ;
×
1086
    }
1087

1088
    if (!input_perm_check(attr)) {
29,946✔
1089
        chkpnt_os << "/* OUTPUT-ONLY: ";
23✔
1090
    }
1091
    if ( attr->type == TRICK_STL ) {
29,946✔
1092
        chkpnt_os << "// STL: " << lname ;
2,541✔
1093
    } else {
1094
        chkpnt_os << lname << " = ";
27,405✔
1095

1096
        write_rvalue( chkpnt_os, (void*)address, attr, curr_dim, offset);
27,405✔
1097
        chkpnt_os << ";";
27,405✔
1098

1099
        // Check if we need to add decimal comments for hexfloat values
1100
        bool should_add_decimal_comment = hexfloat_decimal_comment_checkpoint && hexfloat_checkpoint && (attr->type == TRICK_FLOAT || attr->type == TRICK_DOUBLE);
27,405✔
1101

1102
        // Add decimal comment for hexfloat values
1103
        if (should_add_decimal_comment) {
27,405✔
1104
            // Temporarily disable hexfloat to get decimal representation
1105
            bool saved_hexfloat = hexfloat_checkpoint;
×
1106
            hexfloat_checkpoint = false;
×
1107

1108
            // Capture decimal output to string stream
1109
            std::stringstream decimal_ss;
×
1110
            write_rvalue( decimal_ss, (void*)address, attr, curr_dim, offset);
×
1111

1112
            // Restore hexfloat setting
1113
            hexfloat_checkpoint = saved_hexfloat;
×
1114

1115
            // Add // to each line of the decimal output
1116
            std::string decimal_str = decimal_ss.str();
×
1117
            std::istringstream iss(decimal_str);
×
1118
            std::string line;
×
1119
            bool first_line = true;
×
1120
            
1121
            while (std::getline(iss, line)) {
×
1122
                if (first_line) {
×
1123
                    chkpnt_os << std::endl << "// " << lname << " = " << line;
×
1124
                    first_line = false;
×
1125
                } else {
1126
                    chkpnt_os << std::endl << "//" << line;
×
1127
                }
1128
            }
1129
        }
×
1130
    }
1131
    if (!input_perm_check(attr)) {
29,946✔
1132
        chkpnt_os << "*/";
23✔
1133
    }
1134
    chkpnt_os << std::endl;
29,946✔
1135
    chkpnt_os.flush();
29,946✔
1136

1137
}
62,348✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc