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

nasa / trick / 18137782273

30 Sep 2025 05:08PM UTC coverage: 55.79% (-0.09%) from 55.875%
18137782273

Pull #1966

github

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

6 of 30 new or added lines in 5 files covered. (20.0%)

10 existing lines in 3 files now uncovered.

12353 of 22142 relevant lines covered (55.79%)

270851.69 hits per line

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

68.43
/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 <stdlib.h>
17
#include <math.h>
18
#include <string.h>
19

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

48
// MEMBER FUNCTION
49
Trick::ClassicCheckPointAgent::ClassicCheckPointAgent( Trick::MemoryManager *MM) {
627✔
50

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

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

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

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

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

72
    std::string name ;
110,350✔
73
    int ii;
74
    int n_elements = leftside_stack.size();
55,175✔
75

76
    for (ii = 0; ii < n_elements ; ii++) {
213,490✔
77

78
        VarNameElement & element = leftside_stack[ii];
158,315✔
79

80
        switch( element.type) {
158,315✔
81

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

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

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

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

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

109
    const char *type_spec;
110

111
    type_spec = trickTypeCharString(info->type, info->user_type_name);
2,546✔
112

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

117
    if ( info->num_index == 0 ) {
2,546✔
118

119
        chkpnt_os << type_spec << " " << info->name << ";\n";
93✔
120

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

124
        chkpnt_os << type_spec;
2,453✔
125

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

132
        chkpnt_os << " " << info->name ;
2,453✔
133

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

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

146

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

153
   Helper function for getCompositeSubReference.
154
.
155
*/
156

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

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

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

198
    return &(A[i]);
675✔
199
}
200

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

207
   A return value of 1 indicates an error occured. A return value of 0 indicates
208
   success.
209

210
   The following BNF production describes a valid sub-reference:
211

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

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

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

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

237
    char* rAddr = (char*)reference_address;
675✔
238
    char* sAddr = (char*)structure_address;
675✔
239

240
    long referenceOffset = (long)rAddr - (long)sAddr;
675✔
241

242
    // selected ATTRIBUTES stucture from A (singular)
243
    ATTRIBUTES* Ai;
244

245

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

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

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

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

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

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

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

288
        offset = (long) rAddr - ((long) sAddr + Ai->offset);
×
289
        size = last_size = Ai->size;
×
290

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

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

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

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

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

343
/*********** Member is an arrayed struct **************************************/ 
344

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

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

358

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

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

370
/**** Go find the subreference for the arrayed struct member and append *********/
371

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

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

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

395
    return 0;
1✔
396
}
397

398

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

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

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

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

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

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

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

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

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

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

463
    /** @par Detailed Description: */
464

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

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

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

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

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

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

593
    } else {
594
        return(-1);
×
595
    }
596
    return(0);
840✔
597
}
598

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

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

618
    void* src_addr;
619

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

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

679
                enum_attr = (ENUM_ATTR*)attr->attr;
80✔
680

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

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

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

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

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

811
    std::string reference_string;
1,900✔
812

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

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

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

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

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

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

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

841
                int ii;
842
                int n_l_ptrs, n_r_ptrs;
843

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

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

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

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

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

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

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

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

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

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

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

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

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

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

976
        write_singleton( chkpnt_os, address, attr, offset);
27,033✔
977

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

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

985
            void* pointer = *(void**)((char*)address + offset * sizeof(void*));
941✔
986

987
            ref_string = ref_string_from_ptr( pointer, attr, curr_dim);
941✔
988

989
            chkpnt_os << ref_string.c_str() ;
941✔
990

991
        } else { // Fixed dimension
992

993
            char* src_addr;
994

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

999
                int use_quoted_string;
1000

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

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

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

1021

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

1030

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

1033
                    write_quoted_str(chkpnt_os, src_addr);
343✔
1034

1035
                } else {
1036

1037
                    int ii, jj;
1038
                    int array_len;
1039

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

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

1045
                    chkpnt_os << "\n";
2,232✔
1046

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

1052
                    for (ii = 0; ii < array_len ; ii++ ) {
8,329✔
1053

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

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

1072
                }
2,575✔
1073

1074
            } else { // Not the final fixed dimension.
1075

1076
                int ii;
1077

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

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

1091
                chkpnt_os << "\n";
4✔
1092

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

1100
    } else {
1101
        chkpnt_os << "/*ERROR*/";
×
1102

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

1106
        return;
×
1107
    }
1108
}
1109

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

1114
    std::string lname = left_side_name();
55,175✔
1115

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

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

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

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

1144
        write_rvalue( chkpnt_os, (void*)address, attr, curr_dim, offset);
24,195✔
1145
        chkpnt_os << ";";
24,195✔
1146

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

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

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

1160
            // Restore hexfloat setting
NEW
1161
            hexfloat_checkpoint = saved_hexfloat;
×
1162

1163
            // Add // to each line of the decimal output
NEW
1164
            std::string decimal_str = decimal_ss.str();
×
NEW
1165
            std::istringstream iss(decimal_str);
×
NEW
1166
            std::string line;
×
NEW
1167
            bool first_line = true;
×
1168
            
NEW
1169
            while (std::getline(iss, line)) {
×
NEW
1170
                if (first_line) {
×
NEW
1171
                    chkpnt_os << std::endl << "// " << lname << " = " << line;
×
NEW
1172
                    first_line = false;
×
1173
                } else {
NEW
1174
                    chkpnt_os << std::endl << "//" << line;
×
1175
                }
1176
            }
1177
        }
1178
    }
1179
    if (!input_perm_check(attr)) {
26,383✔
1180
        chkpnt_os << "*/";
21✔
1181
    }
1182
    chkpnt_os << std::endl;
26,383✔
1183
    chkpnt_os.flush();
26,383✔
1184

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