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

nasa / trick / 22691708164

04 Mar 2026 10:08PM UTC coverage: 55.827%. First build
22691708164

Pull #1965

github

web-flow
Merge 79bda524a into 43b8fa7c8
Pull Request #1965: 1964 methods return size one pointers

153 of 184 new or added lines in 3 files covered. (83.15%)

12632 of 22627 relevant lines covered (55.83%)

306388.08 hits per line

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

68.79
/trick_source/sim_services/CheckPointAgent/ClassicCheckPointerAgent.cpp
1
#include "trick/MemoryManager.hh"
2
#include "trick/parameter_types.h"
3
#include "trick/io_alloc.h"
4
#include "trick/wcs_ext.h"
5
#include "trick/bitfield_proto.h"
6
#include "trick/message_proto.h"
7
#include "trick/message_type.h"
8

9
#include "trick/ClassicCheckPointAgent.hh"
10
#include "trick/AttributesUtils.hh"
11
#include "trick/ChkPtParseContext.hh"
12

13
#include <string>
14
#include <iostream>
15
#include <iomanip>
16
#include <sstream>
17
#include <stdlib.h>
18
#include <math.h>
19
#include <string.h>
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
// MEMBER FUNCTION
50
Trick::ClassicCheckPointAgent::ClassicCheckPointAgent( Trick::MemoryManager *MM) {
631✔
51

52
   mem_mgr = MM;
631✔
53
   reduced_checkpoint = 1;
631✔
54
   hexfloat_checkpoint = 0;
631✔
55
   debug_level = 0;
631✔
56
}
631✔
57

58
// MEMBER FUNCTION
59
Trick::ClassicCheckPointAgent::~ClassicCheckPointAgent() { }
1,260✔
60

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

66
bool Trick::ClassicCheckPointAgent::output_perm_check(ATTRIBUTES * attr) {
181,837✔
67
    return (attr->io & TRICK_CHKPNT_OUTPUT) ;
181,837✔
68
}
69

70
// MEMBER FUNCTION
71
std::string Trick::ClassicCheckPointAgent::left_side_name() {
62,274✔
72

73
    std::string name ;
124,548✔
74
    int ii;
75
    int n_elements = leftside_stack.size();
62,274✔
76

77
    for (ii = 0; ii < n_elements ; ii++) {
241,370✔
78

79
        VarNameElement & element = leftside_stack[ii];
179,096✔
80

81
        switch( element.type) {
179,096✔
82

83
            case BASE_NAME: {
62,274✔
84
                name = element.name;
62,274✔
85
            } break;
62,274✔
86

87
            case ELEM_NAME: {
67,007✔
88
                name += '.' + element.name;
67,007✔
89
            } break;
67,007✔
90

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

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

107
// MEMBER FUNCTION
108
void Trick::ClassicCheckPointAgent::write_decl(std::ostream& chkpnt_os, ALLOC_INFO *info) {
2,837✔
109

110
    const char *type_spec;
111

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

117
    type_spec = trickTypeCharString(info->type, info->user_type_name);
2,717✔
118

119
    if (info->stcl == TRICK_EXTERN) {
2,717✔
120
        chkpnt_os << "// extern ";
×
121
    }
122

123
    if ( info->num_index == 0 ) {
2,717✔
124

125
        chkpnt_os << type_spec << " " << info->name << ";\n";
95✔
126

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

130
        chkpnt_os << type_spec;
2,622✔
131

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

138
        chkpnt_os << " " << info->name ;
2,622✔
139

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

147
    } else {
148
        // ERROR - num_index cant be negative.
149
    }
150
}
151

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

158
   A return value of 1 indicates an error occured. A return value of 0 indicates
159
   success.
160

161
   The following BNF production describes a valid sub-reference:
162

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

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

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

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

192
    size_t referenceOffset = (size_t)rAddr - (size_t)sAddr;
753✔
193

194
    Trick::AttributesUtils::TraversalResult traversalResult;
195
    int ret = Trick::AttributesUtils::traverse_for_offset(referenceOffset, (size_t)sAddr, A, traversalResult);
753✔
196

197
    if (ret != 0)
753✔
198
    {
NEW
199
        return 1; // Error
×
200
    }
201

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

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

219
/******************************************************************************/
220

221
    ATTRIBUTES *Ai = traversalResult.found_attr;
165✔
222

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

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

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

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

254
        char buf[256];
255
        ret = getCompositeSubReference(rAddr, left_type, sAddr + Ai->offset, (ATTRIBUTES *)Ai->attr, buf);
147✔
256

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

266
/*** Member is an arrayed struct *********************************************/
267

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

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

285
/**** Go find the subreference for the arrayed struct member and append *********/
286

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

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

301
    return 0;
16✔
302
}
303

304
// MEMBER FUNCTION
305
// Get the fully qualified varible name of the Allocation, given the address.
306

307
std::string Trick::ClassicCheckPointAgent::get_var_name( void* addr,
605✔
308
                                                         ATTRIBUTES* A,
309
                                                         void* struct_addr,
310
                                                         std::string name,
311
                                                         ATTRIBUTES** left_type) {
312
    char reference_name[256];
313
    int ret;
314
    std::string var_name;
1,210✔
315

316
    var_name = name;
605✔
317
    ret = getCompositeSubReference( addr, left_type, struct_addr, A, reference_name );
605✔
318

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

330
// MEMBER FUNCTION
331
int Trick::ClassicCheckPointAgent::restore( std::istream* checkpoint_stream) {
24✔
332

333
    ChkPtParseContext* context = new ChkPtParseContext( mem_mgr, checkpoint_stream);
24✔
334
    int status = 0;
24✔
335

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

348
    if (status) {
24✔
349
        std::stringstream ss;
×
350
        ss << "Checkpoint Agent ERROR: Checkpoint restore failed."
×
351
           << std::endl;
×
352
        message_publish(MSG_INFO, ss.str().c_str() );
×
353
    }
354
    delete context ;
24✔
355
    return (status);
24✔
356
}
357

358
// MEMBER FUNCTION
359
int Trick::ClassicCheckPointAgent::is_nil_valued( void* address,
71,941✔
360
                                                  ATTRIBUTES* attr,
361
                                                  int curr_dim,
362
                                                  int offset
363
                                                ) {
364

365
    char* test_addr;
366
    int remaining_dimensions = attr->num_index - curr_dim;
71,941✔
367

368
    /** @par Detailed Description: */
369

370
    /** @par
371
        If we're referencing a singleton then calculate the test-address
372
        from the (base) address, the offset and the data-type. Then
373
        test that calculated address (with the given type) for nil.
374
        If it's nil return 1, otherwise return 0.
375
     */
376
    if (remaining_dimensions ==0) {
71,941✔
377

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

465
    /** @par
466
        If on the otherhand we are referencing an array, then we must consider two cases.
467
     */
468
    } else if (remaining_dimensions > 0) {
4,399✔
469
       int curr_dim_size;
470
       curr_dim_size = attr->index[curr_dim].size ;
4,399✔
471

472
       /**  @par
473
            If the array is unconstrained (i.e., it's a pointer) then we just need to check
474
            whether the pointer is NULL.
475
        */
476
       if ( curr_dim_size == 0) {
4,399✔
477
           test_addr = ((char*)address) + (offset*sizeof(void *));
1,846✔
478
           if (*(char**)test_addr == NULL) return(1);
1,846✔
479

480
       /** @par
481
           If the array (at this dimension) is constrained (i.e., it's a fixed array )
482
           then it is nil if and only if each of it's sub-elements (at the next dimension,
483
           which can themselves be arrays) are nil. So, for each of the elements in current
484
           dimension, we recursively call is_nil_valued() on each of the sub-elements to
485
           find out whether this array is nil valued and return the result.
486
           */
487
       } else {
488
           int ii;
489
           int zerotest;
490

491
           for (ii=0; ii < curr_dim_size; ii++) {
9,752✔
492
               zerotest = is_nil_valued( address, attr, curr_dim+1, offset*curr_dim_size+ii);
9,667✔
493
               if (!(zerotest == 1)) return(zerotest);
9,667✔
494
           }
495
           return(1);
85✔
496
       }
497

498
    } else {
499
        return(-1);
×
500
    }
501
    return(0);
905✔
502
}
503

504
// STATIC FUNCTION
505
static void write_quoted_str( std::ostream& os, const char* s) {
8,547✔
506
    int ii;
507
    int len = strlen(s);
8,547✔
508
    os << "\"" ;
8,547✔
509
    for (ii=0 ; ii<len ; ii++) {
147,570✔
510
        switch ((s)[ii]) {
139,023✔
511
        case '\n': os << "\\n"; break;
54✔
512
        case '\t': os << "\\t"; break;
×
513
        case '\b': os << "\\b"; break;
×
514
        case '\"': os << "\\\""; break;
44✔
515
        default  : os << s[ii] ; break;
138,925✔
516
        }
517
    }
518
    os << "\"" ;
8,547✔
519
}
8,547✔
520

521
void Trick::ClassicCheckPointAgent::write_singleton( std::ostream& chkpnt_os, void* address, ATTRIBUTES* attr, int offset ) {
28,063✔
522

523
    void* src_addr;
524

525
    switch(attr->type) {
28,063✔
526
        case TRICK_VOID:
×
527
            chkpnt_os << std::endl << "// ERROR - VOID data type cannot be checkpointed." << std::endl;
×
528
            message_publish(MSG_ERROR, "Checkpoint Agent ERROR: VOID data type cannot be checkpointed.\n") ;
×
529
        break;
×
530
        case TRICK_UNSIGNED_CHARACTER:
1✔
531
            src_addr = (char*)address + offset * sizeof(unsigned char);
1✔
532
            chkpnt_os << std::dec << (int)*(unsigned char*)src_addr ;
1✔
533
        break;
1✔
534
        case TRICK_BOOLEAN:
2,790✔
535
            src_addr = (char*)address + offset * sizeof(bool);
2,790✔
536
            if (*(bool*)src_addr) {
2,790✔
537
                chkpnt_os << "true" ;
2,789✔
538
            } else {
539
                chkpnt_os << "false" ;
1✔
540
            }
541
        break;
2,790✔
542
        case TRICK_CHARACTER:
1,121✔
543
            src_addr = (char*)address + offset * sizeof(char);
1,121✔
544
            if (isprint( *(char*)src_addr) ) {
1,121✔
545
                chkpnt_os << "'" << *(char*)src_addr << "'" ;
682✔
546
            } else {
547
                unsigned int ch = *(unsigned char*)src_addr;
439✔
548
                  chkpnt_os << "'\\x" << std::hex << ch << "'" ;
439✔
549
            }
550
        break;
1,121✔
551
        case TRICK_WCHAR: {
×
552
            src_addr = (char*)address + offset * sizeof(wchar_t);
×
553
            char buff[16] = {0};
×
554
            wctomb(buff,*(wchar_t*)src_addr);
×
555
            chkpnt_os << std::dec << buff;
×
556
            }
557
            break;
×
558
        case TRICK_SHORT:
8✔
559
            src_addr = (char*)address + offset * sizeof(short);
8✔
560
            chkpnt_os << std::dec << *(short*)src_addr;
8✔
561
            break;
8✔
562
        case TRICK_UNSIGNED_SHORT:
1,997✔
563
            src_addr = (char*)address + offset * sizeof(unsigned short);
1,997✔
564
            chkpnt_os << std::dec << *(unsigned short*)src_addr;
1,997✔
565
            break;
1,997✔
566
        case TRICK_ENUMERATED: {
88✔
567
                int ii = 0;
88✔
568
                int found = 0;
88✔
569
                int value;
570
                ENUM_ATTR* enum_attr;
571

572
                if ((size_t)attr->size == sizeof(int)) {
88✔
573
                    src_addr = (char*)address + offset * sizeof(int);
88✔
574
                    value =  *(int*)src_addr;
88✔
575
                } else if ((size_t)attr->size == sizeof(short)) {
×
576
                    src_addr = (char*)address + offset * sizeof(short);
×
577
                    value =  *(short*)src_addr;
×
578
                } else {
579
                    std::cerr << __FUNCTION__ << ": enumeration size error." << std::endl;
×
580
                    std::cerr.flush();
×
581
                    value = -1;
×
582
                }
583

584
                enum_attr = (ENUM_ATTR*)attr->attr;
88✔
585

586
                while ( !found && (enum_attr[ii].label[0] != '\0')) {
333✔
587
                   if (value == enum_attr[ii].value) {
245✔
588
                       chkpnt_os << enum_attr[ii].label;
88✔
589
                       found = 1;
88✔
590
                   }
591
                   ii++;
245✔
592
                }
593
                if (!found) {
88✔
594
                    chkpnt_os << std::dec << value;
×
595
                }
596

597
            } break;
88✔
598
        case TRICK_INTEGER:
7,380✔
599
            src_addr = (char*)address + offset * sizeof(int);
7,380✔
600
            chkpnt_os << std::dec << *(int*)src_addr;
7,380✔
601
            break;
7,380✔
602
        case TRICK_UNSIGNED_INTEGER:
321✔
603
            src_addr = (char*)address + offset * sizeof(unsigned int);
321✔
604
            chkpnt_os << std::dec << *(unsigned int*)src_addr;
321✔
605
            break;
321✔
606
        case TRICK_LONG:
41✔
607
            src_addr = (char*)address + offset * sizeof(long);
41✔
608
            chkpnt_os << std::dec << *(long*)src_addr;
41✔
609
            break;
41✔
610
        case TRICK_UNSIGNED_LONG:
15✔
611
            src_addr = (char*)address + offset * sizeof(unsigned long);
15✔
612
            chkpnt_os << std::dec << *(unsigned long*)src_addr;
15✔
613
            break;
15✔
614
        case TRICK_FLOAT:
4✔
615
            src_addr = (char*)address + offset * sizeof(float);
4✔
616
            if (fpclassify( *(float*)src_addr) != FP_NAN) {
4✔
617
                if (hexfloat_checkpoint) {
4✔
618
                    double temp_dbl = *(float*)src_addr;
×
619
                    unsigned char* byte_p = (unsigned char*)&temp_dbl;
×
620
                    chkpnt_os << "0g";
×
621
                    for (int ii=sizeof(double)-1 ; ii>= 0 ; ii--) {
×
622
                        chkpnt_os << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)byte_p[ii];
×
623
                    }
624
                } else {
625
                    chkpnt_os << std::setprecision(8) << *(float*)src_addr;
4✔
626
                }
627
            } else {
628
                chkpnt_os << "NAN";
×
629
            }
630
            break;
4✔
631
        case TRICK_DOUBLE:
5,226✔
632
            src_addr = (char*)address + offset * sizeof(double);
5,226✔
633
            if (fpclassify( *(double*)src_addr) != FP_NAN) {
5,226✔
634
                if (hexfloat_checkpoint) {
5,226✔
635
                    double temp_dbl = *(double*)src_addr;
4✔
636
                    unsigned char* byte_p = (unsigned char*)&temp_dbl;
4✔
637
                    chkpnt_os << "0g";
4✔
638
                    for (int ii=sizeof(double)-1 ; ii>= 0 ; ii--) {
36✔
639
                        chkpnt_os << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)byte_p[ii];
32✔
640
                    }
641
                } else {
642
                    chkpnt_os << std::setprecision(16) << *(double*)src_addr;
5,222✔
643
                }
644
            } else {
645
                chkpnt_os << "NAN";
×
646
            }
647
            break;
5,226✔
648
        case TRICK_BITFIELD: {
×
649
                int sbf = 0;
×
650
                src_addr = (char*)address + offset * (size_t)attr->size;
×
651
                if (attr->size == sizeof(int)) {
×
652
                     sbf = extract_bitfield_any( *(int*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
653
                } else if (attr->size == sizeof(short)) {
×
654
                     sbf = extract_bitfield_any( *(short*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
655
                } else if (attr->size == sizeof(char)) {
×
656
                     sbf = extract_bitfield_any( *(char*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
657
                } else {
658
                     message_publish(MSG_ERROR, "Checkpoint Agent INTERNAL ERROR:\n"
×
659
                                                "Unsupported bitfield size (%d) bytes.\n", attr->size) ;
660
                }
661
                chkpnt_os << std::dec << sbf;
×
662
            } break;
×
663
        case TRICK_UNSIGNED_BITFIELD: {
×
664
                int bf = 0;
×
665
                src_addr = (char*)address + offset * (size_t)attr->size;
×
666
                if (attr->size == sizeof(int)) {
×
667
                     bf = extract_unsigned_bitfield_any( *(unsigned int*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
668
                } else if (attr->size == sizeof(short)) {
×
669
                     bf = extract_unsigned_bitfield_any( *(unsigned short*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
670
                } else if (attr->size == sizeof(char)) {
×
671
                     bf = extract_unsigned_bitfield_any( *(unsigned char*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
672
                } else {
673
                     message_publish(MSG_ERROR, "Checkpoint Agent INTERNAL ERROR:\n"
×
674
                                                "Unsupported bitfield size (%d) bytes.\n", attr->size) ;
675
                }
676
                chkpnt_os << std::dec << bf;
×
677
            } break;
×
678
        case TRICK_LONG_LONG:
900✔
679
            src_addr = (char*)address + offset * sizeof(long long);
900✔
680
            chkpnt_os << std::dec << *(long long*)src_addr;
900✔
681
            break;
900✔
682
        case TRICK_UNSIGNED_LONG_LONG:
18✔
683
            src_addr = (char*)address + offset * sizeof(unsigned long long);
18✔
684
            chkpnt_os << std::dec << *(unsigned long long*)src_addr;
18✔
685
            break;
18✔
686
        case  TRICK_FILE_PTR:
×
687
            src_addr = (char*)address + offset * sizeof(void*);
×
688
            chkpnt_os << *(void**)src_addr;
×
689
            break;
×
690
        case TRICK_STRING:
8,153✔
691
            src_addr = (char*)address + offset * sizeof(std::string);
8,153✔
692
            write_quoted_str(chkpnt_os, (*(std::string*)src_addr).c_str());
8,153✔
693
            break;
8,153✔
694
        case TRICK_OPAQUE_TYPE:
×
695
            chkpnt_os << std::endl << "// ERROR - OPAQUE data type (" << attr->type_name << ") cannot be checkpointed." << std::endl;
×
696
            message_publish(MSG_ERROR, "Checkpoint Agent ERROR: OPAQUE data type (%s) cannot be checkpointed.\n", attr->type_name) ;
×
697
        break;
×
698
        default:
×
699
            chkpnt_os << "0";
×
700
            message_publish(MSG_ERROR, "Checkpoint Agent file %s: Unhandled Type (%d).\n", __FILE__, attr->type) ;
×
701
            break;
×
702
    }
703
}
28,063✔
704

705
// MEMBER FUNCTION
706
// Get the variable-name associated with the given variable-address and data-type.
707
// If no data-type is specified, (i.e., if attr == NULL), then the name will refer
708
// to the (inner-most) primitive data-type associated with the address.
709

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

713
std::string Trick::ClassicCheckPointAgent::
1,002✔
714
    ref_string_from_ptr( void* pointer, ATTRIBUTES* attr, int curr_dim) {
715

716
    std::string reference_string;
2,004✔
717

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

722
    if (pointer == NULL) {
1,002✔
723
        reference_string = "NULL";
×
724
    } else {
725
        ALLOC_INFO *alloc_info;
726

727
        /** Find the allocation that contains the pointer-address. */
728
        alloc_info = mem_mgr->get_alloc_info_of( pointer);
1,002✔
729

730
        if (alloc_info != NULL) {
1,002✔
731
            // Special handling for character strings: prefer string literal format over allocation reference
732
            // The following info for "char *" is for reference purpose:
733
            // curr_dim = 0
734
            // attr.type = TRICK_CHARACTER (base type)
735
            // attr.num_index = 1 (1D array)
736
            // attr.index[0].size = 0 (not static array)
737
            // attr.size = sizeof(char)
738
            // This prevents anonymous allocations from appearing in subsequent checkpoints
739
            if ((attr != NULL) && (attr->type == TRICK_CHARACTER || attr->type == TRICK_UNSIGNED_CHARACTER) && ((curr_dim + 1) == attr->num_index)) {
965✔
740
                std::stringstream ss;
101✔
741
                write_quoted_str( ss, (const char*)pointer);
101✔
742
                reference_string = ss.str();
101✔
743
            } else {
744
                int alloc_elem_size;
745
                int alloc_elem_index;
746
                int misalignment;
747

748
                alloc_elem_size = alloc_info->size;
864✔
749
                alloc_elem_index = (int) (((long) pointer - (long) alloc_info->start) / alloc_elem_size);
864✔
750
                misalignment = (int) (((long) pointer - (long) alloc_info->start) % alloc_elem_size);
864✔
751

752
                // If type-checking AND the type specifiers match AND  the type we're looking for
753
                // is either not structured or if it is, the attr-list that describes the contents
754
                // of the structure is the same.
755

756
                if ( (attr != NULL) && (attr->type == alloc_info->type) &&
864✔
757
                     ( (attr->type != TRICK_STRUCTURED) || (attr->attr == alloc_info->attr))) {
852✔
758

759
                int ii;
760
                int n_l_ptrs, n_r_ptrs;
761

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

765
                // Calculate the number of pointers (asterisks) on the right side of the assignment.
766
                n_r_ptrs = 0;
258✔
767
                for (ii=0 ; ii <alloc_info->num_index ; ii++) {
490✔
768
                    if (alloc_info->index[ii] == 0) n_r_ptrs++;
232✔
769
                }
770

771
                if (n_l_ptrs != (n_r_ptrs + 1)) {
258✔
772
                    reference_string = "NULL /*ERROR: # asterisks disagree.*/";
×
773
                } else {
774
                    if (misalignment == 0) {
258✔
775
                        std::stringstream workss;
516✔
776
                        if (alloc_info->name != NULL) {
258✔
777
                            workss << "&" << alloc_info->name;
258✔
778
                            if (alloc_info->num_index != 0) {
258✔
779
                                workss << "[" << alloc_elem_index << "]";
166✔
780
                            }
781
                            reference_string = workss.str();
258✔
782
                        } else {
783
                            std::stringstream ss;
×
784
                            ss << "Checkpoint Agent ERROR: The name of the allocation at " << alloc_info->start << " is NULL."
×
785
                               << "Therefore, Trick::ClassicCheckPointAgent::ref_string_from_ptr() can't generate a textual reference to it."
×
786
                               << std::endl;
×
787
                            message_publish(MSG_ERROR, ss.str().c_str() );
×
788
                            reference_string = "ERROR - Allocation name is NULL";
×
789
                        }
790

791
                    } else {
792
                        message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Badly aligned pointer.\n"
×
793
                                                   "   It is not aligned with the data object\n"
794
                                                   "   (of the same type) into which it is pointing.\n") ;
795
                        reference_string = "ERROR - Badly aligned pointer";
×
796
                    }
797
                }
258✔
798
            } else if (alloc_info->type == TRICK_STRUCTURED) {
606✔
799
                // The type specifications don't match, but the right-side is structured,
800
                // so we apparently the matching type is buried in the right hand side structure.
801

802
                if (alloc_info->name != NULL) {
605✔
803
                    std::string rightside;
1,210✔
804
                    std::stringstream element_name;
1,210✔
805
                    element_name << "&" << alloc_info->name;
605✔
806
                    if (alloc_info->num_index != 0) {
605✔
807
                        element_name << '[' << alloc_elem_index << ']';
54✔
808
                    }
809
                    rightside = get_var_name( pointer,
605✔
810
                                              alloc_info->attr,
811
                                              (char *) alloc_info->start + (alloc_elem_index * alloc_info->size),
605✔
812
                                              element_name.str(),
1,210✔
813
                                              &attr
814
                                            );
605✔
815
                    reference_string = rightside;
605✔
816
                } else {
817
                    std::stringstream ss;
×
818
                    ss << "Checkpoint Agent ERROR: The name of the allocation at " << alloc_info->start << " is NULL."
×
819
                       << "Therefore, Trick::ClassicCheckPointAgent::ref_string_from_ptr() can't generate a textual reference to it."
×
820
                       << std::endl;
×
821
                    message_publish(MSG_ERROR, ss.str().c_str() );
×
822
                    reference_string = "ERROR - Allocation name is NULL";
×
823
                }
824
            } else { // The type specifications don't match, and the right hand side is not structured
825

826
                if (attr != NULL) {
1✔
827
                    const char* left_type_spec  = trickTypeCharString(attr->type, "");
×
828
                    const char* right_type_spec = trickTypeCharString(alloc_info->type, alloc_info->user_type_name);
×
829
                    message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Type mismatch. Type specifications disagree.\n"
×
830
                                               "   The left side type specifier is \"%s\" but the right side is \"%s\".\n",
831
                                    left_type_spec, right_type_spec) ;
832
                    reference_string = "ERROR - Type specifications disagree";
×
833
                } else {
834

835
                    if (misalignment == 0) {
1✔
836
                        std::stringstream workss;
2✔
837

838
                        if (alloc_info->name != NULL) {
1✔
839
                            workss << "&" << alloc_info->name;
1✔
840
                            if (alloc_info->num_index != 0) {
1✔
841
                                workss << "[" << alloc_elem_index << "]";
×
842
                            }
843
                            reference_string = workss.str();
1✔
844
                        } else {
845
                            std::stringstream ss;
×
846
                            ss << "Checkpoint Agent ERROR: The name of the allocation at " << alloc_info->start << " is NULL."
×
847
                               << "Therefore, Trick::ClassicCheckPointAgent::ref_string_from_ptr() can't generate a textual reference to it."
×
848
                               << std::endl;
×
849
                            message_publish(MSG_ERROR, ss.str().c_str() );
×
850
                            reference_string = "ERROR - Allocation name is NULL";
×
851
                        }
852

853
                    } else {
854
                        message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Badly aligned pointer.\n"
×
855
                                                   "   It is not aligned with the data object\n"
856
                                                   "   (of the same type) into which it is pointing.\n") ;
857
                        reference_string = "ERROR - Badly Aligned Pointer";
×
858
                    }
859
                }
860

861
                }
862
            }
863
        } else if ((attr != NULL) && ((curr_dim + 1) == attr->num_index)) {
37✔
864

865
            if (attr->type == TRICK_CHARACTER) {
37✔
866
                std::stringstream ss;
37✔
867
                write_quoted_str( ss, (const char*)pointer);
37✔
868
                reference_string = ss.str();
37✔
869
            } else if (attr->type == TRICK_WCHAR) {
×
870
                message_publish(MSG_ERROR, "Checkpoint Agent ERROR: TRICK_WCHAR not fully supported yet.\n") ;
×
871
                reference_string = "ERROR: TRICK_WCHAR not fully supported yet.";
×
872
            } else {
873
                std::string lname = left_side_name();
×
874
                message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Pointer <%p> in \"%s\" is not in Trick managed memory\n"
×
875
                                           "nor is it a character pointer.\n", pointer, lname.c_str()) ;
876
                reference_string = "ERROR - Pointer not in Trick managed memory";
×
877
            }
37✔
878

879
        } else {
880
            std::string lname = left_side_name();
×
881
            message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Pointer <%p> in \"%s\" is not in Trick managed memory\n"
×
882
                                       "nor is it a character pointer.\n", pointer, lname.c_str()) ;
883
            reference_string = "ERROR - Pointer not in Trick managed memory";
×
884
        }
885
    }
886
    return( reference_string);
2,004✔
887
}
888

889
// MEMBER FUNCTION
890
void Trick::ClassicCheckPointAgent::write_rvalue( std::ostream& chkpnt_os, void* address, ATTRIBUTES* attr, int curr_dim, int offset) {
31,781✔
891

892
    // If the variable that we are pointing to is Un-arrayed
893
    if (curr_dim == attr->num_index) {
31,781✔
894

895
        write_singleton( chkpnt_os, address, attr, offset);
28,063✔
896

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

900
        // If the variable is a pointer
901
        if (attr->index[curr_dim].size == 0) {
3,718✔
902
            std::string ref_string;
1,986✔
903

904
            void* pointer = *(void**)((char*)address + offset * sizeof(void*));
993✔
905

906
            ref_string = ref_string_from_ptr( pointer, attr, curr_dim);
993✔
907

908
            chkpnt_os << ref_string.c_str() ;
993✔
909

910
        } else { // Fixed dimension
911

912
            char* src_addr;
913

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

918
                int use_quoted_string;
919

920
                // If ALL but the last of the elements of a character array
921
                // "isprintable" AND the last is '\0' then print out the array
922
                // as a quoted string. Otherwise print out each of the characters.
923

924
                use_quoted_string = 1;
2,721✔
925
                if (attr->type == TRICK_CHARACTER) {
2,721✔
926

927
                    int array_len = attr->index[curr_dim].size;
304✔
928
                    int ii = array_len - 1;
304✔
929
                    src_addr = (char*)address + offset * array_len * sizeof(char);
304✔
930
                    if (src_addr[ii] != '\0') {
304✔
931
                        use_quoted_string = 0;
23✔
932
                    }
933
                    ii--;
304✔
934
                    while ( use_quoted_string && (ii >= 0) ) {
1,097✔
935
                        use_quoted_string = isprint( src_addr[ii]);
793✔
936
                        ii--;
793✔
937
                    }
938
                }
939

940

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

949

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

952
                    write_quoted_str(chkpnt_os, src_addr);
256✔
953

954
                } else {
955

956
                    int ii, jj;
957
                    int array_len;
958

959
                    // Determine the number of array elements we need to print out
960
                    // to get all of the non-zero values.
961

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

964
                    chkpnt_os << "\n";
2,465✔
965

966
                    for (ii=0 ; ii < curr_dim+1 ; ii++) {
4,935✔
967
                        chkpnt_os << "    ";
2,470✔
968
                    }
969
                    chkpnt_os << "{";
2,465✔
970

971
                    for (ii = 0; ii < array_len ; ii++ ) {
6,668✔
972

973
                        if (ii > 0) {
4,203✔
974
                            chkpnt_os << ", ";
1,738✔
975

976
                            // Conditionally line-break and indent.
977
                            if (( (ii+1) % array_elements_per_line[attr->type]) == 0 ) {
1,738✔
978
                                // Line-break.
979
                                chkpnt_os << "\n";
198✔
980
                                // Indent.
981
                                for (jj=0 ; jj < curr_dim+1 ; jj++) {
396✔
982
                                    chkpnt_os << "    ";
198✔
983
                                }
984
                                chkpnt_os << " ";
198✔
985
                            }
986
                        }
987
                        write_rvalue( chkpnt_os, address, attr, curr_dim + 1, offset * attr->index[curr_dim].size + ii);
4,203✔
988
                    }
989
                    chkpnt_os << "}";
2,465✔
990

991
                }
2,721✔
992

993
            } else { // Not the final fixed dimension.
994

995
                int ii;
996

997
                chkpnt_os << "\n";
4✔
998
                for (ii=0 ; ii < curr_dim+1 ; ii++) {
8✔
999
                    chkpnt_os << "    ";
4✔
1000
                }
1001
                chkpnt_os << "{";
4✔
1002

1003
                for (ii=0 ; ii< attr->index[curr_dim].size ; ii++) {
265✔
1004
                    if (ii > 0) {
261✔
1005
                        chkpnt_os << ",";
257✔
1006
                    }
1007
                    write_rvalue( chkpnt_os, address, attr, curr_dim + 1, offset * attr->index[curr_dim].size + ii);
261✔
1008
                }
1009

1010
                chkpnt_os << "\n";
4✔
1011

1012
                for (ii=0 ; ii < curr_dim+1 ; ii++) {
8✔
1013
                    chkpnt_os << "    " ;
4✔
1014
                }
1015
                chkpnt_os << "}";
4✔
1016
            }
1017
        }
1018

1019
    } else {
1020
        chkpnt_os << "/*ERROR*/";
×
1021

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

1025
        return;
×
1026
    }
1027
}
1028

1029
// MEMBER FUNCTION
1030
// Create an assignment statement.
1031
void Trick::ClassicCheckPointAgent::assign_rvalue(std::ostream& chkpnt_os, void* address, ATTRIBUTES* attr, int curr_dim, int offset) {
62,274✔
1032

1033
    std::string lname = left_side_name();
62,274✔
1034

1035
    if (!output_perm_check(attr)) {
62,274✔
1036
        if (debug_level) {
×
1037
            message_publish(MSG_DEBUG, "Checkpoint Agent INFO: No assignment generated for \"%s\" "
×
1038
                                       "because its io specification does not allow it.\n", lname.c_str()) ;
1039
        }
1040
        return;
×
1041
    }
1042

1043
    if ((reduced_checkpoint && is_nil_valued( (void*)address, attr, curr_dim, offset ) ) ) {
62,274✔
1044
        if (debug_level) {
32,433✔
1045
            message_publish(MSG_DEBUG, "Checkpoint Agent INFO: No assignment generated for \"%s\" "
×
1046
                                       "because its value is nil and the reduced_checkpoint flag is set.\n", lname.c_str()) ;
1047
        }
1048
        return;
32,433✔
1049
    }
1050

1051
    if (debug_level) {
29,841✔
1052
        message_publish(MSG_DEBUG, "Checkpoint Agent INFO: Generating assignment for [%p] %s.\n",(void*)address, lname.c_str()) ;
×
1053
    }
1054

1055
    if (!input_perm_check(attr)) {
29,841✔
1056
        chkpnt_os << "/* OUTPUT-ONLY: ";
23✔
1057
    }
1058
    if ( attr->type == TRICK_STL ) {
29,841✔
1059
        chkpnt_os << "// STL: " << lname ;
2,524✔
1060
    } else {
1061
        chkpnt_os << lname << " = ";
27,317✔
1062

1063
        write_rvalue( chkpnt_os, (void*)address, attr, curr_dim, offset);
27,317✔
1064
        chkpnt_os << ";";
27,317✔
1065

1066
        // Check if we need to add decimal comments for hexfloat values
1067
        bool should_add_decimal_comment = hexfloat_decimal_comment_checkpoint && hexfloat_checkpoint && (attr->type == TRICK_FLOAT || attr->type == TRICK_DOUBLE);
27,317✔
1068

1069
        // Add decimal comment for hexfloat values
1070
        if (should_add_decimal_comment) {
27,317✔
1071
            // Temporarily disable hexfloat to get decimal representation
1072
            bool saved_hexfloat = hexfloat_checkpoint;
×
1073
            hexfloat_checkpoint = false;
×
1074

1075
            // Capture decimal output to string stream
1076
            std::stringstream decimal_ss;
×
1077
            write_rvalue( decimal_ss, (void*)address, attr, curr_dim, offset);
×
1078

1079
            // Restore hexfloat setting
1080
            hexfloat_checkpoint = saved_hexfloat;
×
1081

1082
            // Add // to each line of the decimal output
1083
            std::string decimal_str = decimal_ss.str();
×
1084
            std::istringstream iss(decimal_str);
×
1085
            std::string line;
×
1086
            bool first_line = true;
×
1087
            
1088
            while (std::getline(iss, line)) {
×
1089
                if (first_line) {
×
1090
                    chkpnt_os << std::endl << "// " << lname << " = " << line;
×
1091
                    first_line = false;
×
1092
                } else {
1093
                    chkpnt_os << std::endl << "//" << line;
×
1094
                }
1095
            }
1096
        }
1097
    }
1098
    if (!input_perm_check(attr)) {
29,841✔
1099
        chkpnt_os << "*/";
23✔
1100
    }
1101
    chkpnt_os << std::endl;
29,841✔
1102
    chkpnt_os.flush();
29,841✔
1103

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

© 2026 Coveralls, Inc