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

nasa / trick / 18045388585

26 Sep 2025 05:54PM UTC coverage: 55.824% (-0.05%) from 55.875%
18045388585

Pull #1966

github

web-flow
Merge 5ef82d23e into f8fc2f0d0
Pull Request #1966: Introduce the option to include decimal comment lines for hexfloat values in the checkpoint file.

6 of 31 new or added lines in 5 files covered. (19.35%)

91 existing lines in 1 file now uncovered.

12361 of 22143 relevant lines covered (55.82%)

262024.69 hits per line

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

68.32
/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/ChkPtParseContext.hh"
11

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

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

50
// MEMBER FUNCTION
51
Trick::ClassicCheckPointAgent::ClassicCheckPointAgent( Trick::MemoryManager *MM) {
627✔
52

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

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

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

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

71
// MEMBER FUNCTION
72
std::string Trick::ClassicCheckPointAgent::left_side_name() {
55,175✔
73

74
    std::string name ;
55,175✔
75
    int ii;
76
    int n_elements = leftside_stack.size();
55,175✔
77

78
    for (ii = 0; ii < n_elements ; ii++) {
213,490✔
79

80
        VarNameElement & element = leftside_stack[ii];
158,315✔
81

82
        switch( element.type) {
158,315✔
83

84
            case BASE_NAME: {
55,175✔
85
                name = element.name;
55,175✔
86
            } break;
55,175✔
87

88
            case ELEM_NAME: {
59,122✔
89
                name += '.' + element.name;
59,122✔
90
            } break;
59,122✔
91

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

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

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

111
    const char *type_spec;
112

113
    type_spec = trickTypeCharString(info->type, info->user_type_name);
2,546✔
114

115
    if (info->stcl == TRICK_EXTERN) {
2,546✔
UNCOV
116
        chkpnt_os << "// extern ";
×
117
    }
118

119
    if ( info->num_index == 0 ) {
2,546✔
120

121
        chkpnt_os << type_spec << " " << info->name << ";\n";
93✔
122

123
    } else if ((info->num_index > 0) && (info->num_index <= TRICK_MAX_INDEX)) {
2,453✔
124
        int ii;
125

126
        chkpnt_os << type_spec;
2,453✔
127

128
        ii = info->num_index-1;
2,453✔
129
        while ((ii >= 0) && (info->index[ii] == 0)) {
2,573✔
130
            chkpnt_os << "*";
120✔
131
            ii --;
120✔
132
        }
133

134
        chkpnt_os << " " << info->name ;
2,453✔
135

136
        ii = 0;
2,453✔
137
        while ((ii < info->num_index) && (info->index[ii] != 0)) {
4,905✔
138
            chkpnt_os << "[" << info->index[ii] << "]" ;
2,452✔
139
            ii ++;
2,452✔
140
        }
141
          chkpnt_os << ";" << std::endl;
2,453✔
142

143
    } else {
144
        // ERROR - num_index cant be negative.
145
    }
146
}
2,546✔
147

148

149
// STATIC FUNCTION
150
/* 
151
   Given an offset, that is within the bounds of a composite
152
   object (i.e., a struct or class instance), return the corresponding 
153
   ATTRIBUTES pointer (singular).
154

155
   Helper function for getCompositeSubReference.
156
.
157
*/
158

159
static ATTRIBUTES* findMember(ATTRIBUTES* A, long referenceOffset) {
675✔
160
    int i = 0;
675✔
161
    int j;
162
    int temp_size;
163
    /* Find the member which contains the address pointed to by rAddr */
164
    while ((A[i].name[0] != '\0')) {
4,822✔
165

166
        // if mod bit 0 is set, A[i] is a reference. Width of reference is stored
167
        // in mod bits 3-8. We could use sizeof(void*), but that is implementation
168
        // specific and not required by C++ standard.
169
        if ((A[i].mods & 1) == 1) {
4,296✔
170
          temp_size = ((A[i].mods >> 3) & 0x3F);
5✔
171
          // Calculate the size (temp_size) of the referenced member variable.
172
        } else if (A[i].num_index != 0) {
4,291✔
173
            // if size of last valid index is 0, then we are looking at a pointer
174
            if (A[i].index[A[i].num_index - 1].size == 0) {
403✔
175
                temp_size = sizeof(void*);
340✔
176
            } else {
177
                temp_size = A[i].size;
63✔
178
            }
179
            for (j = 0; j < A[i].num_index; j++) {
467✔
180
                if (A[i].index[j].size != 0) {
404✔
181
                    temp_size *= A[i].index[j].size;
64✔
182
                } else {
183
                    break;
340✔
184
                }
185
            }
186
        } else {
187
            temp_size = A[i].size;
3,888✔
188
        }
189

190
        // if the reference is not to this member variable, move on to the next member variable.
191
        if ( ( referenceOffset <  (long) ( A[i].offset)   ) ||
4,296✔
192
             ( referenceOffset >= (long) ( A[i].offset + temp_size))
955✔
193
           ) {
194
            i++;
4,147✔
195
        } else {
196
            break;
197
        }
198
    }
199

200
    return &(A[i]);
675✔
201
}
202

203
// STATIC FUNCTION
204
/*
205
   Given an address, that is within the bounds of a composite
206
   object (i.e., a struct or class instance), store the corresponding sub-name
207
   in reference_name buffer and return.
208

209
   A return value of 1 indicates an error occured. A return value of 0 indicates
210
   success.
211

212
   The following BNF production describes a valid sub-reference:
213

214
   <sub_reference> --> ""
215
                     | "+" + <offset>
216
                     | "[" + <index>+ "]" + <sub_reference>
217
                     | "." + <member_name> + <sub_reference>
218

219
   <offset> is an integer. It is the the reference offset minus the offset of
220
   the last data member.
221
   <index> is an integer. It is an array index.
222
   <member_name> is a name of a member of the given composite type.
223
*/
224

225
static int getCompositeSubReference(
675✔
226
    void*        reference_address, /* Address we are looking for */
227
    ATTRIBUTES** left_type,         /* Attributes of type we are looking for */
228
    void*        structure_address, /* Address of struct we are in */
229
    ATTRIBUTES*  A,                 /* Attributes of current struct we are in */
230
    char* reference_name            /* destination buffer of composite subreference */
231
    ) {
232

233
    int   j, m;
234
    long  offset;
235
    int   my_index[9];
236
    int   ret;
237
    int   size, last_size;
238

239
    char* rAddr = (char*)reference_address;
675✔
240
    char* sAddr = (char*)structure_address;
675✔
241

242
    long referenceOffset = (long)rAddr - (long)sAddr;
675✔
243

244
    // selected ATTRIBUTES stucture from A (singular)
245
    ATTRIBUTES* Ai;
246

247

248
    if ( referenceOffset < 0) {
675✔
UNCOV
249
        message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Address to find is less than struct address.\n") ;
×
UNCOV
250
        return 1;
×
251
    }
252

253
    // Find the structure member that corresponds to the reference address.
254
    // If name is empty, we have failed. 
255
    Ai = findMember(A, referenceOffset);
675✔
256

257
/******If failed to find member, set reference_name to offset only and return ****/
258
    if (Ai->name[0] == '\0') {
675✔
259
        /* If we fail to find a member corresponding to the reference address,
260
           it must mean that the ATTRIBUTES don't contain a description for
261
           that particular member, i.e., it was **'ed out. In this case, we can only
262
           represent the reference_address as a byte offset into the structure.
263
         */
264
        if (referenceOffset == 0) {
526✔
265
            reference_name[0] = '\0' ;
516✔
266
        } else if (referenceOffset > 0) {
10✔
267
            snprintf(reference_name, (size_t)256, " + %ld" , referenceOffset);
10✔
268
        } else {
UNCOV
269
            return 1; // ERROR
×
270
        }
271
        return 0;
526✔
272
    }
273

274
/******************************************************************************/
275
    
276
/* We found a member corresponding to the reference address, so print it's name. */
277
    snprintf(reference_name, (size_t)256, ".%s", Ai->name);
149✔
278

279
/* If the referenced member variable is an intrinsic type */
280
    if (Ai->type != TRICK_STRUCTURED) {
149✔
281

282
/* If the reference address is non-array or a pointer, return reference_name as is */
283
        if((Ai->num_index == 0) || (Ai->index[0].size == 0)) {
14✔
284
            return 0;
14✔
285
        }
286

287
/* else, rAddr is pointing to an array, determine its dimensions and determine 
288
   the element pointed to by rAddr. Then print the index and return */
289

UNCOV
290
        offset = (long) rAddr - ((long) sAddr + Ai->offset);
×
UNCOV
291
        size = last_size = Ai->size;
×
292

293
        /* Calculate the number of fixed dimensions. */
294
        int num_fixed_dims = 0;
×
295
        for (j = 0; j < Ai->num_index; j++) {
×
UNCOV
296
            if (Ai->index[j].size > 0) {
×
UNCOV
297
                num_fixed_dims++;
×
298
            }
299
        }
300

301
        // Calculate the array indices for the right-side.
302
        for (j = num_fixed_dims - 1; j >= 0; j--) {
×
303
            size *= Ai->index[j].size;
×
304
            if(!size) {
×
UNCOV
305
              std::cerr << "Checkpoint Agent " << __FUNCTION__ << " ERROR: divide by zero during array indices calculation" << std::endl;
×
306
              return 1;
×
307
            }
308
            my_index[j] = (int) ((offset % size) / last_size);
×
UNCOV
309
            offset -= last_size * my_index[j];
×
UNCOV
310
            last_size = size;
×
311
        }
312

313
        for (j = 0; j < num_fixed_dims; j++) {
×
314
            size_t len = strlen(reference_name);
×
UNCOV
315
            size_t rem = (size_t)256 - len;
×
316
            snprintf(&reference_name[len], rem, "[%d]", my_index[j]);
×
317
        }
UNCOV
318
    return 0;
×
319
    }
320
/******** TRICK_STRUCTURED ****************************************************/
321
    /* if it is a reference, do nothing and return */
322
    if ((Ai->mods & 1) == 1) { // Ai->type == TRICK_STRUCTURED
135✔
323
        return 0;
1✔
324
    }
325
/*if member is an unarrayed struct, continue to call getCompositeSubReference.*/
326
    if (Ai->num_index == 0) {
134✔
327
        char buf[256];
328
        ret = getCompositeSubReference( rAddr, left_type, sAddr + Ai->offset, (ATTRIBUTES *) Ai->attr, buf);
131✔
329

330
        if (ret == 0) {
131✔
331
            size_t len = strlen(reference_name);
131✔
332
            size_t rem = (size_t)256 - len;
131✔
333
            snprintf(&reference_name[len], rem, "%s", buf);
131✔
334
        } else {
UNCOV
335
            return 1; // ERROR.
×
336
        }
337
    return 0;
131✔
338
    }
339

340
/***** If the member is not a pointer do nothing and return *******************/
341
    if (Ai->index[0].size == 0) {
3✔
342
        return 0;
2✔
343
    }
344

345
/*********** Member is an arrayed struct **************************************/ 
346

347
    offset = (long) rAddr - ((long) sAddr + Ai->offset);
1✔
348
    size = last_size = Ai->size;
1✔
349

350
    /* Calculate the indices into the array */
351
    for (j = Ai->num_index - 1; j >= 0; j--) {
3✔
352
        if (Ai->index[j].size != 0) {
2✔
353
            size *= Ai->index[j].size;
2✔
354
        }
355
        my_index[j] = (int) ((offset % size) / last_size);
2✔
356
        offset -= last_size * my_index[j];
2✔
357
        last_size = size;
2✔
358
    }
359

360

361
    for (j = 0; j < Ai->num_index; j++) {
3✔
362
        size_t len = strlen(reference_name);
2✔
363
        size_t rem = (size_t)256 - len;
2✔
364
        snprintf(&reference_name[len], rem, "[%d]", my_index[j]);
2✔
365
    }
366

367
    /* if left_type specifies the current member, stop here */
368
    if ( (left_type != NULL) && (*left_type != NULL) && (Ai->attr == (*left_type)->attr)) {
1✔
UNCOV
369
        return 0;
×
370
    } 
371

372
/**** Go find the subreference for the arrayed struct member and append *********/
373

374
    /* get the offset into the array that rAddr points to */
375
    offset = 0;
1✔
376
    for (j = 0; j < Ai->num_index; j++) {
3✔
377
      m = my_index[j];
2✔
378
      for(int k = j + 1; m && (k < Ai->num_index); k++) {
3✔
379
        m *= Ai->index[k].size;
1✔
380
      }
381
      offset += m*Ai->size;
2✔
382
    }
383

384
    {
385
        char buf[256];
386
        ret = getCompositeSubReference( rAddr, left_type, sAddr + Ai->offset + offset, (ATTRIBUTES *) Ai->attr, buf);
1✔
387

388
        if (ret == 0) {
1✔
389
            size_t len = strlen(reference_name);
1✔
390
            size_t rem = (size_t)256 - len;
1✔
391
            snprintf(&reference_name[len], rem, "%s", buf);
1✔
392
        } else {
UNCOV
393
            return 1; // ERROR
×
394
        }
395
    }
396

397
    return 0;
1✔
398
}
399

400

401
// MEMBER FUNCTION
402
// Get the fully qualified varible name of the Allocation, given the address.
403

404
std::string Trick::ClassicCheckPointAgent::get_var_name( void* addr,
543✔
405
                                                         ATTRIBUTES* A,
406
                                                         void* struct_addr,
407
                                                         std::string name,
408
                                                         ATTRIBUTES** left_type) {
409
    char reference_name[256];
410
    int ret;
411
    std::string var_name;
543✔
412

413
    var_name = name;
543✔
414
    ret = getCompositeSubReference( addr, left_type, struct_addr, A, reference_name );
543✔
415

416
    if (ret == 0) {
543✔
417
        var_name += reference_name;
543✔
418
    } else {
419
          std::stringstream ss;
×
420
          ss << "Checkpoint Agent ERROR: Unable to create a subreference of variable \"" << name << "\"."
×
UNCOV
421
             << std::endl;
×
UNCOV
422
          message_publish(MSG_ERROR, ss.str().c_str() );
×
423
    }
424
    return (var_name);
1,086✔
425
}
426

427
// MEMBER FUNCTION
428
int Trick::ClassicCheckPointAgent::restore( std::istream* checkpoint_stream) {
22✔
429

430
    ChkPtParseContext* context = new ChkPtParseContext( mem_mgr, checkpoint_stream);
22✔
431
    int status = 0;
22✔
432

433
    if ( CCP_parse( context)) {
22✔
UNCOV
434
        status = 1;
×
435
    } else if ((context->bad_declaration_count > 0) ||
22✔
436
               (context->bad_assignment_count > 0)) {
22✔
437
        std::stringstream ss;
×
438
        ss << "Checkpoint Agent ERROR: " << context->bad_declaration_count << " invalid declaration(s) "
×
439
           << "and " << context->bad_assignment_count << " invalid assignment(s)."
×
440
           << std::endl;
×
UNCOV
441
        message_publish(MSG_ERROR, ss.str().c_str() );
×
UNCOV
442
        status = 1;
×
443
    }
444

445
    if (status) {
22✔
446
        std::stringstream ss;
×
447
        ss << "Checkpoint Agent ERROR: Checkpoint restore failed."
×
UNCOV
448
           << std::endl;
×
UNCOV
449
        message_publish(MSG_INFO, ss.str().c_str() );
×
450
    }
451
    delete context ;
22✔
452
    return (status);
22✔
453
}
454

455
// MEMBER FUNCTION
456
int Trick::ClassicCheckPointAgent::is_nil_valued( void* address,
63,911✔
457
                                                  ATTRIBUTES* attr,
458
                                                  int curr_dim,
459
                                                  int offset
460
                                                ) {
461

462
    char* test_addr;
463
    int remaining_dimensions = attr->num_index - curr_dim;
63,911✔
464

465
    /** @par Detailed Description: */
466

467
    /** @par
468
        If we're referencing a singleton then calculate the test-address
469
        from the (base) address, the offset and the data-type. Then
470
        test that calculated address (with the given type) for nil.
471
        If it's nil return 1, otherwise return 0.
472
     */
473
    if (remaining_dimensions ==0) {
63,911✔
474

475
        switch (attr->type) {
59,728✔
476
           case TRICK_CHARACTER :
6,584✔
477
           case TRICK_UNSIGNED_CHARACTER :
478
               test_addr = (char*)address + offset * sizeof(char);
6,584✔
479
               if (*(char*)test_addr == '\0') return(1);
6,584✔
480
               break;
148✔
481
           case TRICK_BOOLEAN:
12,728✔
482
               test_addr = (char*)address + offset * sizeof(bool);
12,728✔
483
               if (*(bool*)test_addr == false) return(1);
12,728✔
484
               break;
2,469✔
485
           case TRICK_WCHAR :
×
486
               test_addr = (char*)address + offset * sizeof(wchar_t);
×
UNCOV
487
               if (*(wchar_t*)test_addr == 0) return(1);
×
UNCOV
488
               break;
×
489
           case TRICK_SHORT :
2,103✔
490
           case TRICK_UNSIGNED_SHORT :
491
               test_addr = (char*)address + offset * sizeof(short);
2,103✔
492
               if (*(short*)test_addr == 0) return(1);
2,103✔
493
               break;
1,754✔
494
           case TRICK_INTEGER :
12,340✔
495
           case TRICK_UNSIGNED_INTEGER :
496
               test_addr = (char*)address + offset * sizeof(int);
12,340✔
497
               if (*(int*)test_addr == 0) return(1);
12,340✔
498
               break;
6,523✔
499
           case TRICK_ENUMERATED :
358✔
500
               if ((size_t)attr->size == sizeof(int)) {
358✔
501
                   test_addr = (char*)address + offset * sizeof(int);
358✔
502
                   if (*(int*)test_addr == 0) return(1);
358✔
503
               } else if ((size_t)attr->size == sizeof(short)) {
×
UNCOV
504
                   test_addr = (char*)address + offset * sizeof(short);
×
505
                   if (*(short*)test_addr == 0) return(1);
×
506
               } else {
UNCOV
507
                   return(-1);
×
508
               }
509
               break;
76✔
510
           case TRICK_LONG :
91✔
511
           case TRICK_UNSIGNED_LONG :
512
               test_addr = (char*)address + offset * sizeof(long);
91✔
513
               if (*(long*)test_addr == 0) return(1);
91✔
514
               break;
43✔
515
           case TRICK_FLOAT :
2✔
516
               test_addr = (char*)address + offset * sizeof(float);
2✔
517
               if (fpclassify( *(float*)test_addr) == FP_ZERO) return(1);
2✔
518
               break;
2✔
519
           case TRICK_DOUBLE :
7,026✔
520
               test_addr = (char*)address + offset * sizeof(double);
7,026✔
521
               if (fpclassify( *(double*)test_addr) == FP_ZERO) return(1);
7,026✔
522
               break;
4,464✔
523
           case TRICK_LONG_LONG :
8,703✔
524
           case TRICK_UNSIGNED_LONG_LONG :
525
               test_addr = (char*)address + offset * sizeof(long long);
8,703✔
526
               if (*(long long*)test_addr == 0) return(1);
8,703✔
527
               break;
745✔
528
           case TRICK_BITFIELD :
×
529
           case TRICK_UNSIGNED_BITFIELD :
530
               test_addr = (char*)address + offset * (size_t)attr->size;
×
531
               if (attr->size == sizeof(int)) {
×
532
                   if (*(int*)test_addr == 0) return(1);
×
533
               } else if (attr->size == sizeof(short)) {
×
534
                   if (*(short*)test_addr == 0) return(1);
×
UNCOV
535
               } else if (attr->size == sizeof(char)) {
×
536
                   if (*(char*)test_addr == 0) return(1);
×
537
               } else {
538
                   message_publish(MSG_ERROR, "Checkpoint Agent INTERNAL ERROR:\n"
×
539
                                              "Unhandled bitfield struct size (%d) in bitfield assignment.\n", attr->size) ;
540
                   return(-1);
×
541
               }
UNCOV
542
               break;
×
543
           case TRICK_FILE_PTR :
×
544
               // FIXME
UNCOV
545
               return(0);
×
546
               break;
547
           case TRICK_STRING :
7,605✔
548
               test_addr = (char*)address + offset * sizeof(void*);
7,605✔
549
               if (*(std::string*)test_addr == "") return(1);
7,605✔
550
               break;
7,131✔
551
           case TRICK_STL :
2,188✔
552
               // Can't test properly, always return 0 to indicate the STL is not empty.
553
               return(0);
2,188✔
554
               break;
555
           default :
×
UNCOV
556
               message_publish(MSG_ERROR, "Checkpoint Agent file %s: Unhandled Type (%d).\n", __FILE__, attr->type) ;
×
UNCOV
557
               return(-1);
×
558
               break;
559
        }
560
        return(0);
23,355✔
561

562
    /** @par
563
        If on the otherhand we are referencing an array, then we must consider two cases.
564
     */
565
    } else if (remaining_dimensions > 0) {
4,183✔
566
       int curr_dim_size;
567
       curr_dim_size = attr->index[curr_dim].size ;
4,183✔
568

569
       /**  @par
570
            If the array is unconstrained (i.e., it's a pointer) then we just need to check
571
            whether the pointer is NULL.
572
        */
573
       if ( curr_dim_size == 0) {
4,183✔
574
           test_addr = ((char*)address) + (offset*sizeof(void *));
1,735✔
575
           if (*(char**)test_addr == NULL) return(1);
1,735✔
576

577
       /** @par
578
           If the array (at this dimension) is constrained (i.e., it's a fixed array )
579
           then it is nil if and only if each of it's sub-elements (at the next dimension,
580
           which can themselves be arrays) are nil. So, for each of the elements in current
581
           dimension, we recursively call is_nil_valued() on each of the sub-elements to
582
           find out whether this array is nil valued and return the result.
583
           */
584
       } else {
585
           int ii;
586
           int zerotest;
587

588
           for (ii=0; ii < curr_dim_size; ii++) {
8,862✔
589
               zerotest = is_nil_valued( address, attr, curr_dim+1, offset*curr_dim_size+ii);
8,736✔
590
               if (!(zerotest == 1)) return(zerotest);
8,736✔
591
           }
592
           return(1);
126✔
593
       }
594

595
    } else {
UNCOV
596
        return(-1);
×
597
    }
598
    return(0);
840✔
599
}
600

601
// STATIC FUNCTION
602
static void write_quoted_str( std::ostream& os, const char* s) {
7,595✔
603
    int ii;
604
    int len = strlen(s);
7,595✔
605
    os << "\"" ;
7,595✔
606
    for (ii=0 ; ii<len ; ii++) {
132,356✔
607
        switch ((s)[ii]) {
124,761✔
608
        case '\n': os << "\\n"; break;
54✔
UNCOV
609
        case '\t': os << "\\t"; break;
×
UNCOV
610
        case '\b': os << "\\b"; break;
×
611
        case '\"': os << "\\\""; break;
62✔
612
        default  : os << s[ii] ; break;
124,645✔
613
        }
614
    }
615
    os << "\"" ;
7,595✔
616
}
7,595✔
617

618
void Trick::ClassicCheckPointAgent::write_singleton( std::ostream& chkpnt_os, void* address, ATTRIBUTES* attr, int offset ) {
27,033✔
619

620
    void* src_addr;
621

622
    switch(attr->type) {
27,033✔
623
        case TRICK_VOID:
×
624
            chkpnt_os << std::endl << "// ERROR - VOID data type cannot be checkpointed." << std::endl;
×
UNCOV
625
            message_publish(MSG_ERROR, "Checkpoint Agent ERROR: VOID data type cannot be checkpointed.\n") ;
×
UNCOV
626
        break;
×
627
        case TRICK_UNSIGNED_CHARACTER:
1✔
628
            src_addr = (char*)address + offset * sizeof(unsigned char);
1✔
629
            chkpnt_os << std::dec << (int)*(unsigned char*)src_addr ;
1✔
630
        break;
1✔
631
        case TRICK_BOOLEAN:
2,470✔
632
            src_addr = (char*)address + offset * sizeof(bool);
2,470✔
633
            if (*(bool*)src_addr) {
2,470✔
634
                chkpnt_os << "true" ;
2,469✔
635
            } else {
636
                chkpnt_os << "false" ;
1✔
637
            }
638
        break;
2,470✔
639
        case TRICK_CHARACTER:
3,243✔
640
            src_addr = (char*)address + offset * sizeof(char);
3,243✔
641
            if (isprint( *(char*)src_addr) ) {
3,243✔
642
                chkpnt_os << "'" << *(char*)src_addr << "'" ;
2,802✔
643
            } else {
644
                unsigned int ch = *(unsigned char*)src_addr;
441✔
645
                  chkpnt_os << "'\\x" << std::hex << ch << "'" ;
441✔
646
            }
647
        break;
3,243✔
648
        case TRICK_WCHAR: {
×
649
            src_addr = (char*)address + offset * sizeof(wchar_t);
×
650
            char buff[16] = {0};
×
UNCOV
651
            wctomb(buff,*(wchar_t*)src_addr);
×
652
            chkpnt_os << std::dec << buff;
×
653
            }
UNCOV
654
            break;
×
655
        case TRICK_SHORT:
8✔
656
            src_addr = (char*)address + offset * sizeof(short);
8✔
657
            chkpnt_os << std::dec << *(short*)src_addr;
8✔
658
            break;
8✔
659
        case TRICK_UNSIGNED_SHORT:
1,750✔
660
            src_addr = (char*)address + offset * sizeof(unsigned short);
1,750✔
661
            chkpnt_os << std::dec << *(unsigned short*)src_addr;
1,750✔
662
            break;
1,750✔
663
        case TRICK_ENUMERATED: {
80✔
664
                int ii = 0;
80✔
665
                int found = 0;
80✔
666
                int value;
667
                ENUM_ATTR* enum_attr;
668

669
                if ((size_t)attr->size == sizeof(int)) {
80✔
670
                    src_addr = (char*)address + offset * sizeof(int);
80✔
671
                    value =  *(int*)src_addr;
80✔
672
                } else if ((size_t)attr->size == sizeof(short)) {
×
UNCOV
673
                    src_addr = (char*)address + offset * sizeof(short);
×
674
                    value =  *(short*)src_addr;
×
675
                } else {
676
                    std::cerr << __FUNCTION__ << ": enumeration size error." << std::endl;
×
UNCOV
677
                    std::cerr.flush();
×
UNCOV
678
                    value = -1;
×
679
                }
680

681
                enum_attr = (ENUM_ATTR*)attr->attr;
80✔
682

683
                while ( !found && (enum_attr[ii].label[0] != '\0')) {
303✔
684
                   if (value == enum_attr[ii].value) {
223✔
685
                       chkpnt_os << enum_attr[ii].label;
80✔
686
                       found = 1;
80✔
687
                   }
688
                   ii++;
223✔
689
                }
690
                if (!found) {
80✔
UNCOV
691
                    chkpnt_os << std::dec << value;
×
692
                }
693

694
            } break;
80✔
695
        case TRICK_INTEGER:
6,569✔
696
            src_addr = (char*)address + offset * sizeof(int);
6,569✔
697
            chkpnt_os << std::dec << *(int*)src_addr;
6,569✔
698
            break;
6,569✔
699
        case TRICK_UNSIGNED_INTEGER:
291✔
700
            src_addr = (char*)address + offset * sizeof(unsigned int);
291✔
701
            chkpnt_os << std::dec << *(unsigned int*)src_addr;
291✔
702
            break;
291✔
703
        case TRICK_LONG:
37✔
704
            src_addr = (char*)address + offset * sizeof(long);
37✔
705
            chkpnt_os << std::dec << *(long*)src_addr;
37✔
706
            break;
37✔
707
        case TRICK_UNSIGNED_LONG:
11✔
708
            src_addr = (char*)address + offset * sizeof(unsigned long);
11✔
709
            chkpnt_os << std::dec << *(unsigned long*)src_addr;
11✔
710
            break;
11✔
711
        case TRICK_FLOAT:
4✔
712
            src_addr = (char*)address + offset * sizeof(float);
4✔
713
            if (fpclassify( *(float*)src_addr) != FP_NAN) {
4✔
714
                if (hexfloat_checkpoint) {
4✔
715
                    double temp_dbl = *(float*)src_addr;
×
716
                    unsigned char* byte_p = (unsigned char*)&temp_dbl;
×
717
                    chkpnt_os << "0g";
×
UNCOV
718
                    for (int ii=sizeof(double)-1 ; ii>= 0 ; ii--) {
×
UNCOV
719
                        chkpnt_os << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)byte_p[ii];
×
720
                    }
721
                } else {
722
                    chkpnt_os << std::setprecision(8) << *(float*)src_addr;
4✔
723
                }
724
            } else {
UNCOV
725
                chkpnt_os << "NAN";
×
726
            }
727
            break;
4✔
728
        case TRICK_DOUBLE:
4,601✔
729
            src_addr = (char*)address + offset * sizeof(double);
4,601✔
730
            if (fpclassify( *(double*)src_addr) != FP_NAN) {
4,601✔
731
                if (hexfloat_checkpoint) {
4,601✔
732
                    double temp_dbl = *(double*)src_addr;
4✔
733
                    unsigned char* byte_p = (unsigned char*)&temp_dbl;
4✔
734
                    chkpnt_os << "0g";
4✔
735
                    for (int ii=sizeof(double)-1 ; ii>= 0 ; ii--) {
36✔
736
                        chkpnt_os << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)byte_p[ii];
32✔
737
                    }
738
                } else {
739
                    chkpnt_os << std::setprecision(16) << *(double*)src_addr;
4,597✔
740
                }
741
            } else {
UNCOV
742
                chkpnt_os << "NAN";
×
743
            }
744
            break;
4,601✔
745
        case TRICK_BITFIELD: {
×
746
                int sbf = 0;
×
747
                src_addr = (char*)address + offset * (size_t)attr->size;
×
748
                if (attr->size == sizeof(int)) {
×
749
                     sbf = extract_bitfield_any( *(int*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
750
                } else if (attr->size == sizeof(short)) {
×
751
                     sbf = extract_bitfield_any( *(short*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
UNCOV
752
                } else if (attr->size == sizeof(char)) {
×
753
                     sbf = extract_bitfield_any( *(char*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
754
                } else {
UNCOV
755
                     message_publish(MSG_ERROR, "Checkpoint Agent INTERNAL ERROR:\n"
×
756
                                                "Unsupported bitfield size (%d) bytes.\n", attr->size) ;
757
                }
758
                chkpnt_os << std::dec << sbf;
×
759
            } break;
×
760
        case TRICK_UNSIGNED_BITFIELD: {
×
761
                int bf = 0;
×
762
                src_addr = (char*)address + offset * (size_t)attr->size;
×
763
                if (attr->size == sizeof(int)) {
×
764
                     bf = extract_unsigned_bitfield_any( *(unsigned int*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
765
                } else if (attr->size == sizeof(short)) {
×
766
                     bf = extract_unsigned_bitfield_any( *(unsigned short*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
UNCOV
767
                } else if (attr->size == sizeof(char)) {
×
768
                     bf = extract_unsigned_bitfield_any( *(unsigned char*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
769
                } else {
UNCOV
770
                     message_publish(MSG_ERROR, "Checkpoint Agent INTERNAL ERROR:\n"
×
771
                                                "Unsupported bitfield size (%d) bytes.\n", attr->size) ;
772
                }
UNCOV
773
                chkpnt_os << std::dec << bf;
×
UNCOV
774
            } break;
×
775
        case TRICK_LONG_LONG:
733✔
776
            src_addr = (char*)address + offset * sizeof(long long);
733✔
777
            chkpnt_os << std::dec << *(long long*)src_addr;
733✔
778
            break;
733✔
779
        case TRICK_UNSIGNED_LONG_LONG:
16✔
780
            src_addr = (char*)address + offset * sizeof(unsigned long long);
16✔
781
            chkpnt_os << std::dec << *(unsigned long long*)src_addr;
16✔
782
            break;
16✔
783
        case  TRICK_FILE_PTR:
×
784
            src_addr = (char*)address + offset * sizeof(void*);
×
UNCOV
785
            chkpnt_os << *(void**)src_addr;
×
UNCOV
786
            break;
×
787
        case TRICK_STRING:
7,219✔
788
            src_addr = (char*)address + offset * sizeof(std::string);
7,219✔
789
            write_quoted_str(chkpnt_os, (*(std::string*)src_addr).c_str());
7,219✔
790
            break;
7,219✔
791
        case TRICK_OPAQUE_TYPE:
×
792
            chkpnt_os << std::endl << "// ERROR - OPAQUE data type (" << attr->type_name << ") cannot be checkpointed." << std::endl;
×
793
            message_publish(MSG_ERROR, "Checkpoint Agent ERROR: OPAQUE data type (%s) cannot be checkpointed.\n", attr->type_name) ;
×
794
        break;
×
795
        default:
×
796
            chkpnt_os << "0";
×
UNCOV
797
            message_publish(MSG_ERROR, "Checkpoint Agent file %s: Unhandled Type (%d).\n", __FILE__, attr->type) ;
×
UNCOV
798
            break;
×
799
    }
800
}
27,033✔
801

802
// MEMBER FUNCTION
803
// Get the variable-name associated with the given variable-address and data-type.
804
// If no data-type is specified, (i.e., if attr == NULL), then the name will refer
805
// to the (inner-most) primitive data-type associated with the address.
806

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

810
std::string Trick::ClassicCheckPointAgent::
950✔
811
    ref_string_from_ptr( void* pointer, ATTRIBUTES* attr, int curr_dim) {
812

813
    std::string reference_string;
950✔
814

815
    if ((attr != NULL) && ((curr_dim >= attr->num_index) || (attr->index[curr_dim].size != 0))) {
950✔
UNCOV
816
        message_publish(MSG_ERROR, "Checkpoint Agent ERROR: ref_string_from_ptr called with a non-pointer type.\n") ;
×
817
    }
818

819
    if (pointer == NULL) {
950✔
UNCOV
820
        reference_string = "NULL";
×
821
    } else {
822
        ALLOC_INFO *alloc_info;
823

824
        /** Find the allocation that contains the pointer-address. */
825
        alloc_info = mem_mgr->get_alloc_info_of( pointer);
950✔
826

827
        if (alloc_info != NULL) {
950✔
828
            int alloc_elem_size;
829
            int alloc_elem_index;
830
            int misalignment;
831

832
            alloc_elem_size = alloc_info->size;
917✔
833
            alloc_elem_index = (int) (((long) pointer - (long) alloc_info->start) / alloc_elem_size);
917✔
834
            misalignment = (int) (((long) pointer - (long) alloc_info->start) % alloc_elem_size);
917✔
835

836
            // If type-checking AND the type specifiers match AND  the type we're looking for
837
            // is either not structured or if it is, the attr-list that describes the contents
838
            // of the structure is the same.
839

840
            if ( (attr != NULL) && (attr->type == alloc_info->type) &&
917✔
841
                 ( (attr->type != TRICK_STRUCTURED) || (attr->attr == alloc_info->attr))) {
905✔
842

843
                int ii;
844
                int n_l_ptrs, n_r_ptrs;
845

846
                // Calculate the number of pointers (asterisks) on the left side of the assignment.
847
                n_l_ptrs = attr->num_index - curr_dim;
373✔
848

849
                // Calculate the number of pointers (asterisks) on the right side of the assignment.
850
                n_r_ptrs = 0;
373✔
851
                for (ii=0 ; ii <alloc_info->num_index ; ii++) {
720✔
852
                    if (alloc_info->index[ii] == 0) n_r_ptrs++;
347✔
853
                }
854

855
                if (n_l_ptrs != (n_r_ptrs + 1)) {
373✔
UNCOV
856
                    reference_string = "NULL /*ERROR: # asterisks disagree.*/";
×
857
                } else {
858
                    if (misalignment == 0) {
373✔
859
                        std::stringstream workss;
746✔
860
                        if (alloc_info->name != NULL) {
373✔
861
                            workss << "&" << alloc_info->name;
373✔
862
                            if (alloc_info->num_index != 0) {
373✔
863
                                workss << "[" << alloc_elem_index << "]";
285✔
864
                            }
865
                            reference_string = workss.str();
373✔
866
                        } else {
867
                            std::stringstream ss;
×
868
                            ss << "Checkpoint Agent ERROR: The name of the allocation at " << alloc_info->start << " is NULL."
×
869
                               << "Therefore, Trick::ClassicCheckPointAgent::ref_string_from_ptr() can't generate a textual reference to it."
×
870
                               << std::endl;
×
UNCOV
871
                            message_publish(MSG_ERROR, ss.str().c_str() );
×
UNCOV
872
                            reference_string = "ERROR - Allocation name is NULL";
×
873
                        }
874

875
                    } else {
UNCOV
876
                        message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Badly aligned pointer.\n"
×
877
                                                   "   It is not aligned with the data object\n"
878
                                                   "   (of the same type) into which it is pointing.\n") ;
UNCOV
879
                        reference_string = "ERROR - Badly aligned pointer";
×
880
                    }
881
                }
373✔
882
            } else if (alloc_info->type == TRICK_STRUCTURED) {
544✔
883
                // The type specifications don't match, but the right-side is structured,
884
                // so we apparently the matching type is buried in the right hand side structure.
885

886
                if (alloc_info->name != NULL) {
543✔
887
                    std::string rightside;
1,086✔
888
                    std::stringstream element_name;
1,086✔
889
                    element_name << "&" << alloc_info->name;
543✔
890
                    if (alloc_info->num_index != 0) {
543✔
891
                        element_name << '[' << alloc_elem_index << ']';
54✔
892
                    }
893
                    rightside = get_var_name( pointer,
543✔
894
                                              alloc_info->attr,
895
                                              (char *) alloc_info->start + (alloc_elem_index * alloc_info->size),
543✔
896
                                              element_name.str(),
1,086✔
897
                                              &attr
898
                                            );
543✔
899
                    reference_string = rightside;
543✔
900
                } else {
901
                    std::stringstream ss;
×
902
                    ss << "Checkpoint Agent ERROR: The name of the allocation at " << alloc_info->start << " is NULL."
×
903
                       << "Therefore, Trick::ClassicCheckPointAgent::ref_string_from_ptr() can't generate a textual reference to it."
×
904
                       << std::endl;
×
UNCOV
905
                    message_publish(MSG_ERROR, ss.str().c_str() );
×
UNCOV
906
                    reference_string = "ERROR - Allocation name is NULL";
×
907
                }
908
            } else { // The type specifications don't match, and the right hand side is not structured
909

910
                if (attr != NULL) {
1✔
911
                    const char* left_type_spec  = trickTypeCharString(attr->type, "");
×
UNCOV
912
                    const char* right_type_spec = trickTypeCharString(alloc_info->type, alloc_info->user_type_name);
×
UNCOV
913
                    message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Type mismatch. Type specifications disagree.\n"
×
914
                                               "   The left side type specifier is \"%s\" but the right side is \"%s\".\n",
915
                                    left_type_spec, right_type_spec) ;
UNCOV
916
                    reference_string = "ERROR - Type specifications disagree";
×
917
                } else {
918

919
                    if (misalignment == 0) {
1✔
920
                        std::stringstream workss;
2✔
921

922
                        if (alloc_info->name != NULL) {
1✔
923
                            workss << "&" << alloc_info->name;
1✔
924
                            if (alloc_info->num_index != 0) {
1✔
UNCOV
925
                                workss << "[" << alloc_elem_index << "]";
×
926
                            }
927
                            reference_string = workss.str();
1✔
928
                        } else {
929
                            std::stringstream ss;
×
930
                            ss << "Checkpoint Agent ERROR: The name of the allocation at " << alloc_info->start << " is NULL."
×
931
                               << "Therefore, Trick::ClassicCheckPointAgent::ref_string_from_ptr() can't generate a textual reference to it."
×
932
                               << std::endl;
×
UNCOV
933
                            message_publish(MSG_ERROR, ss.str().c_str() );
×
UNCOV
934
                            reference_string = "ERROR - Allocation name is NULL";
×
935
                        }
936

937
                    } else {
UNCOV
938
                        message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Badly aligned pointer.\n"
×
939
                                                   "   It is not aligned with the data object\n"
940
                                                   "   (of the same type) into which it is pointing.\n") ;
UNCOV
941
                        reference_string = "ERROR - Badly Aligned Pointer";
×
942
                    }
943
                }
944

945
            }
946
        } else if ((attr != NULL) && ((curr_dim + 1) == attr->num_index)) {
33✔
947

948
            if (attr->type == TRICK_CHARACTER) {
33✔
949
                std::stringstream ss;
33✔
950
                write_quoted_str( ss, (const char*)pointer);
33✔
951
                reference_string = ss.str();
33✔
952
            } else if (attr->type == TRICK_WCHAR) {
×
UNCOV
953
                message_publish(MSG_ERROR, "Checkpoint Agent ERROR: TRICK_WCHAR not fully supported yet.\n") ;
×
954
                reference_string = "ERROR: TRICK_WCHAR not fully supported yet.";
×
955
            } else {
UNCOV
956
                std::string lname = left_side_name();
×
957
                message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Pointer <%p> in \"%s\" is not in Trick managed memory\n"
×
958
                                           "nor is it a character pointer.\n", pointer, lname.c_str()) ;
UNCOV
959
                reference_string = "ERROR - Pointer not in Trick managed memory";
×
960
            }
33✔
961

962
        } else {
UNCOV
963
            std::string lname = left_side_name();
×
964
            message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Pointer <%p> in \"%s\" is not in Trick managed memory\n"
×
965
                                       "nor is it a character pointer.\n", pointer, lname.c_str()) ;
UNCOV
966
            reference_string = "ERROR - Pointer not in Trick managed memory";
×
967
        }
968
    }
969
    return( reference_string);
950✔
970
}
971

972
// MEMBER FUNCTION
973
void Trick::ClassicCheckPointAgent::write_rvalue( std::ostream& chkpnt_os, void* address, ATTRIBUTES* attr, int curr_dim, int offset) {
30,553✔
974

975
    // If the variable that we are pointing to is Un-arrayed
976
    if (curr_dim == attr->num_index) {
30,553✔
977

978
        write_singleton( chkpnt_os, address, attr, offset);
27,033✔
979

980
    // If the variable that we are pointing to is Arrayed
981
    } else if (curr_dim < attr->num_index) {
3,520✔
982

983
        // If the variable is a pointer
984
        if (attr->index[curr_dim].size == 0) {
3,520✔
985
            std::string ref_string;
1,882✔
986

987
            void* pointer = *(void**)((char*)address + offset * sizeof(void*));
941✔
988

989
            ref_string = ref_string_from_ptr( pointer, attr, curr_dim);
941✔
990

991
            chkpnt_os << ref_string.c_str() ;
941✔
992

993
        } else { // Fixed dimension
994

995
            char* src_addr;
996

997
            // If this is the final, fixed dimension
998
            if (((curr_dim + 1) == attr->num_index) ||
2,579✔
999
                (attr->index[curr_dim + 1].size == 0)) {
60✔
1000

1001
                int use_quoted_string;
1002

1003
                // If ALL but the last of the elements of a character array
1004
                // "isprintable" AND the last is '\0' then print out the array
1005
                // as a quoted string. Otherwise print out each of the characters.
1006

1007
                use_quoted_string = 1;
2,575✔
1008
                if (attr->type == TRICK_CHARACTER) {
2,575✔
1009

1010
                    int array_len = attr->index[curr_dim].size;
410✔
1011
                    int ii = array_len - 1;
410✔
1012
                    src_addr = (char*)address + offset * array_len * sizeof(char);
410✔
1013
                    if (src_addr[ii] != '\0') {
410✔
1014
                        use_quoted_string = 0;
34✔
1015
                    }
1016
                    ii--;
410✔
1017
                    while ( use_quoted_string && (ii >= 0) ) {
3,448✔
1018
                        use_quoted_string = isprint( src_addr[ii]);
3,038✔
1019
                        ii--;
3,038✔
1020
                    }
1021
                }
1022

1023

1024
                // This is necessary due to https://github.com/nasa/trick/issues/1399
1025
                // If there is a string array where the memory is not initialized, the code above
1026
                // can incorrectly decide to write it as a quoted string when it should be an
1027
                // empty array, causing a segfault when the checkpoint is reloaded.
1028
                if (attr->index[curr_dim + 1].size == 0 && ((curr_dim + 1) != attr->num_index)) {
2,575✔
1029
                    use_quoted_string = 0;
56✔
1030
                } 
1031

1032

1033
                if ((attr->type == TRICK_CHARACTER) && use_quoted_string)  {
2,575✔
1034

1035
                    write_quoted_str(chkpnt_os, src_addr);
343✔
1036

1037
                } else {
1038

1039
                    int ii, jj;
1040
                    int array_len;
1041

1042
                    // Determine the number of array elements we need to print out
1043
                    // to get all of the non-zero values.
1044

1045
                    array_len = attr->index[curr_dim].size ;
2,232✔
1046

1047
                    chkpnt_os << "\n";
2,232✔
1048

1049
                    for (ii=0 ; ii < curr_dim+1 ; ii++) {
4,469✔
1050
                        chkpnt_os << "    ";
2,237✔
1051
                    }
1052
                    chkpnt_os << "{";
2,232✔
1053

1054
                    for (ii = 0; ii < array_len ; ii++ ) {
8,329✔
1055

1056
                        if (ii > 0) {
6,097✔
1057
                            chkpnt_os << ", ";
3,865✔
1058

1059
                            // Conditionally line-break and indent.
1060
                            if (( (ii+1) % array_elements_per_line[attr->type]) == 0 ) {
3,865✔
1061
                                // Line-break.
1062
                                chkpnt_os << "\n";
298✔
1063
                                // Indent.
1064
                                for (jj=0 ; jj < curr_dim+1 ; jj++) {
596✔
1065
                                    chkpnt_os << "    ";
298✔
1066
                                }
1067
                                chkpnt_os << " ";
298✔
1068
                            }
1069
                        }
1070
                        write_rvalue( chkpnt_os, address, attr, curr_dim + 1, offset * attr->index[curr_dim].size + ii);
6,097✔
1071
                    }
1072
                    chkpnt_os << "}";
2,232✔
1073

1074
                }
2,575✔
1075

1076
            } else { // Not the final fixed dimension.
1077

1078
                int ii;
1079

1080
                chkpnt_os << "\n";
4✔
1081
                for (ii=0 ; ii < curr_dim+1 ; ii++) {
8✔
1082
                    chkpnt_os << "    ";
4✔
1083
                }
1084
                chkpnt_os << "{";
4✔
1085

1086
                for (ii=0 ; ii< attr->index[curr_dim].size ; ii++) {
265✔
1087
                    if (ii > 0) {
261✔
1088
                        chkpnt_os << ",";
257✔
1089
                    }
1090
                    write_rvalue( chkpnt_os, address, attr, curr_dim + 1, offset * attr->index[curr_dim].size + ii);
261✔
1091
                }
1092

1093
                chkpnt_os << "\n";
4✔
1094

1095
                for (ii=0 ; ii < curr_dim+1 ; ii++) {
8✔
1096
                    chkpnt_os << "    " ;
4✔
1097
                }
1098
                chkpnt_os << "}";
4✔
1099
            }
1100
        }
1101

1102
    } else {
1103
        chkpnt_os << "/*ERROR*/";
×
1104

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

UNCOV
1108
        return;
×
1109
    }
1110
}
1111

1112
// MEMBER FUNCTION
1113
// Create an assignment statement.
1114
void Trick::ClassicCheckPointAgent::assign_rvalue(std::ostream& chkpnt_os, void* address, ATTRIBUTES* attr, int curr_dim, int offset) {
55,175✔
1115

1116
    std::string lname = left_side_name();
55,175✔
1117

1118
    if (!output_perm_check(attr)) {
55,175✔
UNCOV
1119
        if (debug_level) {
×
UNCOV
1120
            message_publish(MSG_DEBUG, "Checkpoint Agent INFO: No assignment generated for \"%s\" "
×
1121
                                       "because its io specification does not allow it.\n", lname.c_str()) ;
1122
        }
UNCOV
1123
        return;
×
1124
    }
1125

1126
    if ((reduced_checkpoint && is_nil_valued( (void*)address, attr, curr_dim, offset ) ) ) {
55,175✔
1127
        if (debug_level) {
28,792✔
UNCOV
1128
            message_publish(MSG_DEBUG, "Checkpoint Agent INFO: No assignment generated for \"%s\" "
×
1129
                                       "because its value is nil and the reduced_checkpoint flag is set.\n", lname.c_str()) ;
1130
        }
1131
        return;
28,792✔
1132
    }
1133

1134
    if (debug_level) {
26,383✔
UNCOV
1135
        message_publish(MSG_DEBUG, "Checkpoint Agent INFO: Generating assignment for [%p] %s.\n",(void*)address, lname.c_str()) ;
×
1136
    }
1137

1138
    if (!input_perm_check(attr)) {
26,383✔
1139
        chkpnt_os << "/* OUTPUT-ONLY: ";
21✔
1140
    }
1141
    if ( attr->type == TRICK_STL ) {
26,383✔
1142
        chkpnt_os << "// STL: " << lname ;
2,188✔
1143
    } else {
1144
        chkpnt_os << lname << " = ";
24,195✔
1145

1146
        // Check if we need to add decimal comments for hexfloat values
1147
        bool should_add_decimal_comment = hexfloat_decimal_comment_checkpoint && hexfloat_checkpoint && (attr->type == TRICK_FLOAT || attr->type == TRICK_DOUBLE);
24,195✔
1148

1149
        write_rvalue( chkpnt_os, (void*)address, attr, curr_dim, offset);
24,195✔
1150
        chkpnt_os << ";";
24,195✔
1151

1152
        // Add decimal comment for hexfloat values
1153
        if (should_add_decimal_comment) {
24,195✔
1154
            // Temporarily disable hexfloat to get decimal representation
NEW
1155
            bool saved_hexfloat = hexfloat_checkpoint;
×
NEW
1156
            hexfloat_checkpoint = false;
×
1157

1158
            // Capture decimal output to string stream
NEW
1159
            std::stringstream decimal_ss;
×
NEW
1160
            write_rvalue( decimal_ss, (void*)address, attr, curr_dim, offset);
×
1161

1162
            // Restore hexfloat setting
NEW
1163
            hexfloat_checkpoint = saved_hexfloat;
×
1164

1165
            // Convert to single line comment by replacing newlines with spaces
NEW
1166
            std::string decimal_str = decimal_ss.str();
×
NEW
1167
            std::replace(decimal_str.begin(), decimal_str.end(), '\n', ' ');
×
1168

1169
            // Remove extra whitespace
NEW
1170
            std::istringstream iss(decimal_str);
×
NEW
1171
            std::string result;
×
1172

1173
            // Use istream_iterator to read all words and join all words
NEW
1174
            std::istream_iterator<std::string> begin(iss);
×
NEW
1175
            std::istream_iterator<std::string> end;
×
1176

NEW
1177
            for (auto it = begin; it != end; ++it) {
×
NEW
UNCOV
1178
                if (!result.empty()) result += " ";
×
NEW
UNCOV
1179
                result += *it;
×
1180
            }
1181

NEW
UNCOV
1182
            chkpnt_os << std::endl << "// " << lname << " = " << result;
×
1183
        }
1184
    }
1185
    if (!input_perm_check(attr)) {
26,383✔
1186
        chkpnt_os << "*/";
21✔
1187
    }
1188
    chkpnt_os << std::endl;
26,383✔
1189
    chkpnt_os.flush();
26,383✔
1190

1191
}
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