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

nasa / trick / 21039148268

15 Jan 2026 04:46PM UTC coverage: 55.67% (-0.2%) from 55.875%
21039148268

Pull #1965

github

web-flow
Merge b6d3aa7f1 into 36fe2139e
Pull Request #1965: 1964 methods return size one pointers

91 of 128 new or added lines in 3 files covered. (71.09%)

1022 existing lines in 21 files now uncovered.

12573 of 22585 relevant lines covered (55.67%)

299072.13 hits per line

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

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

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

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

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

49
// MEMBER FUNCTION
50
Trick::ClassicCheckPointAgent::ClassicCheckPointAgent( Trick::MemoryManager *MM) {
629✔
51

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

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

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

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

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

73
    std::string name ;
117,760✔
74
    int ii;
75
    int n_elements = leftside_stack.size();
58,880✔
76

77
    for (ii = 0; ii < n_elements ; ii++) {
227,951✔
78

79
        VarNameElement & element = leftside_stack[ii];
169,071✔
80

81
        switch( element.type) {
169,071✔
82

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

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

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

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

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

110
    const char *type_spec;
111

112
    type_spec = trickTypeCharString(info->type, info->user_type_name);
2,696✔
113

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

118
    if ( info->num_index == 0 ) {
2,696✔
119

120
        chkpnt_os << type_spec << " " << info->name << ";\n";
94✔
121

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

125
        chkpnt_os << type_spec;
2,602✔
126

127
        ii = info->num_index-1;
2,602✔
128
        while ((ii >= 0) && (info->index[ii] == 0)) {
2,711✔
129
            chkpnt_os << "*";
109✔
130
            ii --;
109✔
131
        }
132

133
        chkpnt_os << " " << info->name ;
2,602✔
134

135
        ii = 0;
2,602✔
136
        while ((ii < info->num_index) && (info->index[ii] != 0)) {
5,203✔
137
            chkpnt_os << "[" << info->index[ii] << "]" ;
2,601✔
138
            ii ++;
2,601✔
139
        }
140
          chkpnt_os << ";" << std::endl;
2,602✔
141

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

147

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

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

158
static ATTRIBUTES* findMember(ATTRIBUTES* A, long referenceOffset) {
714✔
159
    return Trick::AttributesUtils::find_member_by_offset(A, referenceOffset);
714✔
160
}
161

162
// STATIC FUNCTION
163
/*
164
   Given an address, that is within the bounds of a composite
165
   object (i.e., a struct or class instance), store the corresponding sub-name
166
   in reference_name buffer and return.
167

168
   A return value of 1 indicates an error occured. A return value of 0 indicates
169
   success.
170

171
   The following BNF production describes a valid sub-reference:
172

173
   <sub_reference> --> ""
174
                     | "+" + <offset>
175
                     | "[" + <index>+ "]" + <sub_reference>
176
                     | "." + <member_name> + <sub_reference>
177

178
   <offset> is an integer. It is the the reference offset minus the offset of
179
   the last data member.
180
   <index> is an integer. It is an array index.
181
   <member_name> is a name of a member of the given composite type.
182
*/
183

184
static int getCompositeSubReference(
714✔
185
    void*        reference_address, /* Address we are looking for */
186
    ATTRIBUTES** left_type,         /* Attributes of type we are looking for */
187
    void*        structure_address, /* Address of struct we are in */
188
    ATTRIBUTES*  A,                 /* Attributes of current struct we are in */
189
    char* reference_name            /* destination buffer of composite subreference */
190
    ) {
191

192
    int   j, m;
193
    long  offset;
194
    int   my_index[TRICK_MAX_INDEX];
195
    int   ret;
196

197
    char* rAddr = (char*)reference_address;
714✔
198
    char* sAddr = (char*)structure_address;
714✔
199

200
    long referenceOffset = (long)rAddr - (long)sAddr;
714✔
201

202
    // selected ATTRIBUTES stucture from A (singular)
203
    ATTRIBUTES* Ai;
204

205

206
    if ( referenceOffset < 0) {
714✔
207
        message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Address to find is less than struct address.\n") ;
×
208
        return 1;
×
209
    }
210

211
    // Find the structure member that corresponds to the reference address.
212
    // If name is empty, we have failed. 
213
    Ai = findMember(A, referenceOffset);
714✔
214

215
/******If failed to find member, set reference_name to offset only and return ****/
216
    if (Ai->name[0] == '\0') {
714✔
217
        /* If we fail to find a member corresponding to the reference address,
218
           it must mean that the ATTRIBUTES don't contain a description for
219
           that particular member, i.e., it was **'ed out. In this case, we can only
220
           represent the reference_address as a byte offset into the structure.
221
         */
222
        if (referenceOffset == 0) {
557✔
223
            reference_name[0] = '\0' ;
547✔
224
        } else if (referenceOffset > 0) {
10✔
225
            snprintf(reference_name, (size_t)256, " + %ld" , referenceOffset);
10✔
226
        } else {
227
            return 1; // ERROR
×
228
        }
229
        return 0;
557✔
230
    }
231

232
/******************************************************************************/
233
    
234
/* We found a member corresponding to the reference address, so print it's name. */
235
    snprintf(reference_name, (size_t)256, ".%s", Ai->name);
157✔
236

237
/* If the referenced member variable is an intrinsic type */
238
    if (Ai->type != TRICK_STRUCTURED) {
157✔
239

240
/* If the reference address is non-array or a pointer, return reference_name as is */
241
        if((Ai->num_index == 0) || (Ai->index[0].size == 0)) {
14✔
242
            return 0;
14✔
243
        }
244

245
/* else, rAddr is pointing to an array, determine its dimensions and determine 
246
   the element pointed to by rAddr. Then print the index and return */
247

NEW
248
        offset = (long)rAddr - ((long)sAddr + Ai->offset);
×
249
        {
NEW
250
            int num_fixed_dims = 0;
×
NEW
251
            bool ok = Trick::AttributesUtils::compute_fixed_indices_for_linear_offset(*Ai, offset, my_index, num_fixed_dims);
×
NEW
252
            if (!ok)
×
253
            {
254
                std::cerr << "Checkpoint Agent " << __FUNCTION__
NEW
255
                          << " ERROR: divide by zero during array indices calculation" << std::endl;
×
NEW
256
                return 1;
×
257
            }
NEW
258
            for (j = 0; j < num_fixed_dims; j++)
×
259
            {
NEW
260
                size_t len = strlen(reference_name);
×
NEW
261
                size_t rem = (size_t)256 - len;
×
NEW
262
                snprintf(&reference_name[len], rem, "[%d]", my_index[j]);
×
263
            }
264
        }
265
    return 0;
×
266
    }
267
/******** TRICK_STRUCTURED ****************************************************/
268
    /* if it is a reference, do nothing and return */
269
    if ((Ai->mods & 1) == 1) { // Ai->type == TRICK_STRUCTURED
143✔
270
        return 0;
1✔
271
    }
272
/*if member is an unarrayed struct, continue to call getCompositeSubReference.*/
273
    if (Ai->num_index == 0) {
142✔
274
        /* if left_type specifies the current member, stop here */
275
        if ( (left_type != NULL) && (*left_type != NULL) && (Ai->attr == (*left_type)->attr)) {
139✔
UNCOV
276
            return 0;
×
277
        }
278

279
        char buf[256];
280
        ret = getCompositeSubReference( rAddr, left_type, sAddr + Ai->offset, (ATTRIBUTES *) Ai->attr, buf);
139✔
281

282
        if (ret == 0) {
139✔
283
            size_t len = strlen(reference_name);
139✔
284
            size_t rem = (size_t)256 - len;
139✔
285
            snprintf(&reference_name[len], rem, "%s", buf);
139✔
286
        } else {
UNCOV
287
            return 1; // ERROR.
×
288
        }
289
    return 0;
139✔
290
    }
291

292
/***** If the member is not a pointer do nothing and return *******************/
293
    if (Ai->index[0].size == 0) {
3✔
294
        return 0;
2✔
295
    }
296

297
/*** Member is an arrayed struct *********************************************/
298

299
    offset = (long)rAddr - ((long)sAddr + Ai->offset);
1✔
300
    {
301
        int num_fixed_dims = 0;
1✔
302
        bool ok = Trick::AttributesUtils::compute_fixed_indices_for_linear_offset(*Ai, offset, my_index, num_fixed_dims);
1✔
303
        if (!ok)
1✔
304
        {
305
            std::cerr << "Checkpoint Agent " << __FUNCTION__
NEW
306
                      << " ERROR: divide by zero during array indices calculation" << std::endl;
×
NEW
307
            return 1;
×
308
        }
309

310
        for (j = 0; j < Ai->num_index; j++)
3✔
311
        {
312
            size_t len = strlen(reference_name);
2✔
313
            size_t rem = (size_t)256 - len;
2✔
314
            snprintf(&reference_name[len], rem, "[%d]", my_index[j]);
2✔
315
        }
316
    }
317

318
    /* if left_type specifies the current member, stop here */
319
    if ( (left_type != NULL) && (*left_type != NULL) && (Ai->attr == (*left_type)->attr)) {
1✔
UNCOV
320
        return 0;
×
321
    } 
322

323
/**** Go find the subreference for the arrayed struct member and append *********/
324

325
    /* get the offset into the array that rAddr points to */
326
    offset = 0;
1✔
327
    for (j = 0; j < Ai->num_index; j++) {
3✔
328
      m = my_index[j];
2✔
329
      for(int k = j + 1; m && (k < Ai->num_index); k++) {
3✔
330
        m *= Ai->index[k].size;
1✔
331
    }
332
      offset += m*Ai->size;
2✔
333
    }
334

335
    {
336
        char buf[256];
337
        ret = getCompositeSubReference( rAddr, left_type, sAddr + Ai->offset + offset, (ATTRIBUTES *) Ai->attr, buf);
1✔
338

339
        if (ret == 0) {
1✔
340
            size_t len = strlen(reference_name);
1✔
341
            size_t rem = (size_t)256 - len;
1✔
342
            snprintf(&reference_name[len], rem, "%s", buf);
1✔
343
        } else {
UNCOV
344
            return 1; // ERROR
×
345
        }
346
    }
347

348
    return 0;
1✔
349
}
350

351

352
// MEMBER FUNCTION
353
// Get the fully qualified varible name of the Allocation, given the address.
354

355
std::string Trick::ClassicCheckPointAgent::get_var_name( void* addr,
574✔
356
                                                         ATTRIBUTES* A,
357
                                                         void* struct_addr,
358
                                                         std::string name,
359
                                                         ATTRIBUTES** left_type) {
360
    char reference_name[256];
361
    int ret;
362
    std::string var_name;
1,148✔
363

364
    var_name = name;
574✔
365
    ret = getCompositeSubReference( addr, left_type, struct_addr, A, reference_name );
574✔
366

367
    if (ret == 0) {
574✔
368
        var_name += reference_name;
574✔
369
    } else {
UNCOV
370
          std::stringstream ss;
×
UNCOV
371
          ss << "Checkpoint Agent ERROR: Unable to create a subreference of variable \"" << name << "\"."
×
UNCOV
372
             << std::endl;
×
UNCOV
373
          message_publish(MSG_ERROR, ss.str().c_str() );
×
374
    }
375
    return (var_name);
1,148✔
376
}
377

378
// MEMBER FUNCTION
379
int Trick::ClassicCheckPointAgent::restore( std::istream* checkpoint_stream) {
23✔
380

381
    ChkPtParseContext* context = new ChkPtParseContext( mem_mgr, checkpoint_stream);
23✔
382
    int status = 0;
23✔
383

384
    if ( CCP_parse( context)) {
23✔
385
        status = 1;
×
386
    } else if ((context->bad_declaration_count > 0) ||
23✔
387
               (context->bad_assignment_count > 0)) {
23✔
388
        std::stringstream ss;
×
UNCOV
389
        ss << "Checkpoint Agent ERROR: " << context->bad_declaration_count << " invalid declaration(s) "
×
UNCOV
390
           << "and " << context->bad_assignment_count << " invalid assignment(s)."
×
UNCOV
391
           << std::endl;
×
392
        message_publish(MSG_ERROR, ss.str().c_str() );
×
393
        status = 1;
×
394
    }
395

396
    if (status) {
23✔
UNCOV
397
        std::stringstream ss;
×
UNCOV
398
        ss << "Checkpoint Agent ERROR: Checkpoint restore failed."
×
UNCOV
399
           << std::endl;
×
UNCOV
400
        message_publish(MSG_INFO, ss.str().c_str() );
×
401
    }
402
    delete context ;
23✔
403
    return (status);
23✔
404
}
405

406
// MEMBER FUNCTION
407
int Trick::ClassicCheckPointAgent::is_nil_valued( void* address,
68,118✔
408
                                                  ATTRIBUTES* attr,
409
                                                  int curr_dim,
410
                                                  int offset
411
                                                ) {
412

413
    char* test_addr;
414
    int remaining_dimensions = attr->num_index - curr_dim;
68,118✔
415

416
    /** @par Detailed Description: */
417

418
    /** @par
419
        If we're referencing a singleton then calculate the test-address
420
        from the (base) address, the offset and the data-type. Then
421
        test that calculated address (with the given type) for nil.
422
        If it's nil return 1, otherwise return 0.
423
     */
424
    if (remaining_dimensions ==0) {
68,118✔
425

426
        switch (attr->type) {
63,798✔
427
           case TRICK_CHARACTER :
6,976✔
428
           case TRICK_UNSIGNED_CHARACTER :
429
               test_addr = (char*)address + offset * sizeof(char);
6,976✔
430
               if (*(char*)test_addr == '\0') return(1);
6,976✔
431
               break;
120✔
432
           case TRICK_BOOLEAN:
13,557✔
433
               test_addr = (char*)address + offset * sizeof(bool);
13,557✔
434
               if (*(bool*)test_addr == false) return(1);
13,557✔
435
               break;
2,629✔
UNCOV
436
           case TRICK_WCHAR :
×
UNCOV
437
               test_addr = (char*)address + offset * sizeof(wchar_t);
×
UNCOV
438
               if (*(wchar_t*)test_addr == 0) return(1);
×
UNCOV
439
               break;
×
440
           case TRICK_SHORT :
2,241✔
441
           case TRICK_UNSIGNED_SHORT :
442
               test_addr = (char*)address + offset * sizeof(short);
2,241✔
443
               if (*(short*)test_addr == 0) return(1);
2,241✔
444
               break;
1,885✔
445
           case TRICK_INTEGER :
13,144✔
446
           case TRICK_UNSIGNED_INTEGER :
447
               test_addr = (char*)address + offset * sizeof(int);
13,144✔
448
               if (*(int*)test_addr == 0) return(1);
13,144✔
449
               break;
6,949✔
450
           case TRICK_ENUMERATED :
380✔
451
               if ((size_t)attr->size == sizeof(int)) {
380✔
452
                   test_addr = (char*)address + offset * sizeof(int);
380✔
453
                   if (*(int*)test_addr == 0) return(1);
380✔
UNCOV
454
               } else if ((size_t)attr->size == sizeof(short)) {
×
UNCOV
455
                   test_addr = (char*)address + offset * sizeof(short);
×
UNCOV
456
                   if (*(short*)test_addr == 0) return(1);
×
457
               } else {
UNCOV
458
                   return(-1);
×
459
               }
460
               break;
80✔
461
           case TRICK_LONG :
97✔
462
           case TRICK_UNSIGNED_LONG :
463
               test_addr = (char*)address + offset * sizeof(long);
97✔
464
               if (*(long*)test_addr == 0) return(1);
97✔
465
               break;
48✔
466
           case TRICK_FLOAT :
2✔
467
               test_addr = (char*)address + offset * sizeof(float);
2✔
468
               if (fpclassify( *(float*)test_addr) == FP_ZERO) return(1);
2✔
469
               break;
2✔
470
           case TRICK_DOUBLE :
7,526✔
471
               test_addr = (char*)address + offset * sizeof(double);
7,526✔
472
               if (fpclassify( *(double*)test_addr) == FP_ZERO) return(1);
7,526✔
473
               break;
4,805✔
474
           case TRICK_LONG_LONG :
9,392✔
475
           case TRICK_UNSIGNED_LONG_LONG :
476
               test_addr = (char*)address + offset * sizeof(long long);
9,392✔
477
               if (*(long long*)test_addr == 0) return(1);
9,392✔
478
               break;
863✔
479
           case TRICK_BITFIELD :
×
480
           case TRICK_UNSIGNED_BITFIELD :
481
               test_addr = (char*)address + offset * (size_t)attr->size;
×
482
               if (attr->size == sizeof(int)) {
×
UNCOV
483
                   if (*(int*)test_addr == 0) return(1);
×
484
               } else if (attr->size == sizeof(short)) {
×
UNCOV
485
                   if (*(short*)test_addr == 0) return(1);
×
486
               } else if (attr->size == sizeof(char)) {
×
UNCOV
487
                   if (*(char*)test_addr == 0) return(1);
×
488
               } else {
489
                   message_publish(MSG_ERROR, "Checkpoint Agent INTERNAL ERROR:\n"
×
490
                                              "Unhandled bitfield struct size (%d) in bitfield assignment.\n", attr->size) ;
491
                   return(-1);
×
492
               }
UNCOV
493
               break;
×
UNCOV
494
           case TRICK_FILE_PTR :
×
495
               // FIXME
UNCOV
496
               return(0);
×
497
               break;
498
           case TRICK_STRING :
8,101✔
499
               test_addr = (char*)address + offset * sizeof(void*);
8,101✔
500
               if (*(std::string*)test_addr == "") return(1);
8,101✔
501
               break;
7,598✔
502
           case TRICK_STL :
2,382✔
503
               // Can't test properly, always return 0 to indicate the STL is not empty.
504
               return(0);
2,382✔
505
               break;
UNCOV
506
           default :
×
UNCOV
507
               message_publish(MSG_ERROR, "Checkpoint Agent file %s: Unhandled Type (%d).\n", __FILE__, attr->type) ;
×
UNCOV
508
               return(-1);
×
509
               break;
510
        }
511
        return(0);
24,979✔
512

513
    /** @par
514
        If on the otherhand we are referencing an array, then we must consider two cases.
515
     */
516
    } else if (remaining_dimensions > 0) {
4,320✔
517
       int curr_dim_size;
518
       curr_dim_size = attr->index[curr_dim].size ;
4,320✔
519

520
       /**  @par
521
            If the array is unconstrained (i.e., it's a pointer) then we just need to check
522
            whether the pointer is NULL.
523
        */
524
       if ( curr_dim_size == 0) {
4,320✔
525
           test_addr = ((char*)address) + (offset*sizeof(void *));
1,783✔
526
           if (*(char**)test_addr == NULL) return(1);
1,783✔
527

528
       /** @par
529
           If the array (at this dimension) is constrained (i.e., it's a fixed array )
530
           then it is nil if and only if each of it's sub-elements (at the next dimension,
531
           which can themselves be arrays) are nil. So, for each of the elements in current
532
           dimension, we recursively call is_nil_valued() on each of the sub-elements to
533
           find out whether this array is nil valued and return the result.
534
           */
535
       } else {
536
           int ii;
537
           int zerotest;
538

539
           for (ii=0; ii < curr_dim_size; ii++) {
9,368✔
540
               zerotest = is_nil_valued( address, attr, curr_dim+1, offset*curr_dim_size+ii);
9,238✔
541
               if (!(zerotest == 1)) return(zerotest);
9,238✔
542
           }
543
           return(1);
130✔
544
       }
545

546
    } else {
UNCOV
547
        return(-1);
×
548
    }
549
    return(0);
865✔
550
}
551

552
// STATIC FUNCTION
553
static void write_quoted_str( std::ostream& os, const char* s) {
8,035✔
554
    int ii;
555
    int len = strlen(s);
8,035✔
556
    os << "\"" ;
8,035✔
557
    for (ii=0 ; ii<len ; ii++) {
139,672✔
558
        switch ((s)[ii]) {
131,637✔
559
        case '\n': os << "\\n"; break;
54✔
UNCOV
560
        case '\t': os << "\\t"; break;
×
UNCOV
561
        case '\b': os << "\\b"; break;
×
562
        case '\"': os << "\\\""; break;
62✔
563
        default  : os << s[ii] ; break;
131,521✔
564
        }
565
    }
566
    os << "\"" ;
8,035✔
567
}
8,035✔
568

569
void Trick::ClassicCheckPointAgent::write_singleton( std::ostream& chkpnt_os, void* address, ATTRIBUTES* attr, int offset ) {
28,749✔
570

571
    void* src_addr;
572

573
    switch(attr->type) {
28,749✔
UNCOV
574
        case TRICK_VOID:
×
UNCOV
575
            chkpnt_os << std::endl << "// ERROR - VOID data type cannot be checkpointed." << std::endl;
×
UNCOV
576
            message_publish(MSG_ERROR, "Checkpoint Agent ERROR: VOID data type cannot be checkpointed.\n") ;
×
UNCOV
577
        break;
×
578
        case TRICK_UNSIGNED_CHARACTER:
1✔
579
            src_addr = (char*)address + offset * sizeof(unsigned char);
1✔
580
            chkpnt_os << std::dec << (int)*(unsigned char*)src_addr ;
1✔
581
        break;
1✔
582
        case TRICK_BOOLEAN:
2,630✔
583
            src_addr = (char*)address + offset * sizeof(bool);
2,630✔
584
            if (*(bool*)src_addr) {
2,630✔
585
                chkpnt_os << "true" ;
2,629✔
586
            } else {
587
                chkpnt_os << "false" ;
1✔
588
            }
589
        break;
2,630✔
590
        case TRICK_CHARACTER:
3,307✔
591
            src_addr = (char*)address + offset * sizeof(char);
3,307✔
592
            if (isprint( *(char*)src_addr) ) {
3,307✔
593
                chkpnt_os << "'" << *(char*)src_addr << "'" ;
2,842✔
594
            } else {
595
                unsigned int ch = *(unsigned char*)src_addr;
465✔
596
                  chkpnt_os << "'\\x" << std::hex << ch << "'" ;
465✔
597
            }
598
        break;
3,307✔
UNCOV
599
        case TRICK_WCHAR: {
×
600
            src_addr = (char*)address + offset * sizeof(wchar_t);
×
UNCOV
601
            char buff[16] = {0};
×
UNCOV
602
            wctomb(buff,*(wchar_t*)src_addr);
×
UNCOV
603
            chkpnt_os << std::dec << buff;
×
604
            }
UNCOV
605
            break;
×
606
        case TRICK_SHORT:
8✔
607
            src_addr = (char*)address + offset * sizeof(short);
8✔
608
            chkpnt_os << std::dec << *(short*)src_addr;
8✔
609
            break;
8✔
610
        case TRICK_UNSIGNED_SHORT:
1,881✔
611
            src_addr = (char*)address + offset * sizeof(unsigned short);
1,881✔
612
            chkpnt_os << std::dec << *(unsigned short*)src_addr;
1,881✔
613
            break;
1,881✔
614
        case TRICK_ENUMERATED: {
84✔
615
                int ii = 0;
84✔
616
                int found = 0;
84✔
617
                int value;
618
                ENUM_ATTR* enum_attr;
619

620
                if ((size_t)attr->size == sizeof(int)) {
84✔
621
                    src_addr = (char*)address + offset * sizeof(int);
84✔
622
                    value =  *(int*)src_addr;
84✔
623
                } else if ((size_t)attr->size == sizeof(short)) {
×
624
                    src_addr = (char*)address + offset * sizeof(short);
×
UNCOV
625
                    value =  *(short*)src_addr;
×
626
                } else {
UNCOV
627
                    std::cerr << __FUNCTION__ << ": enumeration size error." << std::endl;
×
UNCOV
628
                    std::cerr.flush();
×
UNCOV
629
                    value = -1;
×
630
                }
631

632
                enum_attr = (ENUM_ATTR*)attr->attr;
84✔
633

634
                while ( !found && (enum_attr[ii].label[0] != '\0')) {
318✔
635
                   if (value == enum_attr[ii].value) {
234✔
636
                       chkpnt_os << enum_attr[ii].label;
84✔
637
                       found = 1;
84✔
638
                   }
639
                   ii++;
234✔
640
                }
641
                if (!found) {
84✔
UNCOV
642
                    chkpnt_os << std::dec << value;
×
643
                }
644

645
            } break;
84✔
646
        case TRICK_INTEGER:
6,980✔
647
            src_addr = (char*)address + offset * sizeof(int);
6,980✔
648
            chkpnt_os << std::dec << *(int*)src_addr;
6,980✔
649
            break;
6,980✔
650
        case TRICK_UNSIGNED_INTEGER:
306✔
651
            src_addr = (char*)address + offset * sizeof(unsigned int);
306✔
652
            chkpnt_os << std::dec << *(unsigned int*)src_addr;
306✔
653
            break;
306✔
654
        case TRICK_LONG:
39✔
655
            src_addr = (char*)address + offset * sizeof(long);
39✔
656
            chkpnt_os << std::dec << *(long*)src_addr;
39✔
657
            break;
39✔
658
        case TRICK_UNSIGNED_LONG:
14✔
659
            src_addr = (char*)address + offset * sizeof(unsigned long);
14✔
660
            chkpnt_os << std::dec << *(unsigned long*)src_addr;
14✔
661
            break;
14✔
662
        case TRICK_FLOAT:
4✔
663
            src_addr = (char*)address + offset * sizeof(float);
4✔
664
            if (fpclassify( *(float*)src_addr) != FP_NAN) {
4✔
665
                if (hexfloat_checkpoint) {
4✔
UNCOV
666
                    double temp_dbl = *(float*)src_addr;
×
UNCOV
667
                    unsigned char* byte_p = (unsigned char*)&temp_dbl;
×
UNCOV
668
                    chkpnt_os << "0g";
×
UNCOV
669
                    for (int ii=sizeof(double)-1 ; ii>= 0 ; ii--) {
×
UNCOV
670
                        chkpnt_os << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)byte_p[ii];
×
671
                    }
672
                } else {
673
                    chkpnt_os << std::setprecision(8) << *(float*)src_addr;
4✔
674
                }
675
            } else {
UNCOV
676
                chkpnt_os << "NAN";
×
677
            }
678
            break;
4✔
679
        case TRICK_DOUBLE:
4,942✔
680
            src_addr = (char*)address + offset * sizeof(double);
4,942✔
681
            if (fpclassify( *(double*)src_addr) != FP_NAN) {
4,942✔
682
                if (hexfloat_checkpoint) {
4,942✔
683
                    double temp_dbl = *(double*)src_addr;
4✔
684
                    unsigned char* byte_p = (unsigned char*)&temp_dbl;
4✔
685
                    chkpnt_os << "0g";
4✔
686
                    for (int ii=sizeof(double)-1 ; ii>= 0 ; ii--) {
36✔
687
                        chkpnt_os << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)byte_p[ii];
32✔
688
                    }
689
                } else {
690
                    chkpnt_os << std::setprecision(16) << *(double*)src_addr;
4,938✔
691
                }
692
            } else {
693
                chkpnt_os << "NAN";
×
694
            }
695
            break;
4,942✔
696
        case TRICK_BITFIELD: {
×
697
                int sbf = 0;
×
698
                src_addr = (char*)address + offset * (size_t)attr->size;
×
699
                if (attr->size == sizeof(int)) {
×
UNCOV
700
                     sbf = extract_bitfield_any( *(int*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
701
                } else if (attr->size == sizeof(short)) {
×
UNCOV
702
                     sbf = extract_bitfield_any( *(short*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
UNCOV
703
                } else if (attr->size == sizeof(char)) {
×
704
                     sbf = extract_bitfield_any( *(char*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
705
                } else {
706
                     message_publish(MSG_ERROR, "Checkpoint Agent INTERNAL ERROR:\n"
×
707
                                                "Unsupported bitfield size (%d) bytes.\n", attr->size) ;
708
                }
709
                chkpnt_os << std::dec << sbf;
×
710
            } break;
×
711
        case TRICK_UNSIGNED_BITFIELD: {
×
712
                int bf = 0;
×
713
                src_addr = (char*)address + offset * (size_t)attr->size;
×
714
                if (attr->size == sizeof(int)) {
×
UNCOV
715
                     bf = extract_unsigned_bitfield_any( *(unsigned int*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
716
                } else if (attr->size == sizeof(short)) {
×
UNCOV
717
                     bf = extract_unsigned_bitfield_any( *(unsigned short*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
UNCOV
718
                } else if (attr->size == sizeof(char)) {
×
719
                     bf = extract_unsigned_bitfield_any( *(unsigned char*)src_addr, attr->size, attr->index[0].start, attr->index[0].size);
×
720
                } else {
UNCOV
721
                     message_publish(MSG_ERROR, "Checkpoint Agent INTERNAL ERROR:\n"
×
722
                                                "Unsupported bitfield size (%d) bytes.\n", attr->size) ;
723
                }
UNCOV
724
                chkpnt_os << std::dec << bf;
×
UNCOV
725
            } break;
×
726
        case TRICK_LONG_LONG:
850✔
727
            src_addr = (char*)address + offset * sizeof(long long);
850✔
728
            chkpnt_os << std::dec << *(long long*)src_addr;
850✔
729
            break;
850✔
730
        case TRICK_UNSIGNED_LONG_LONG:
17✔
731
            src_addr = (char*)address + offset * sizeof(unsigned long long);
17✔
732
            chkpnt_os << std::dec << *(unsigned long long*)src_addr;
17✔
733
            break;
17✔
UNCOV
734
        case  TRICK_FILE_PTR:
×
UNCOV
735
            src_addr = (char*)address + offset * sizeof(void*);
×
UNCOV
736
            chkpnt_os << *(void**)src_addr;
×
737
            break;
×
738
        case TRICK_STRING:
7,686✔
739
            src_addr = (char*)address + offset * sizeof(std::string);
7,686✔
740
            write_quoted_str(chkpnt_os, (*(std::string*)src_addr).c_str());
7,686✔
741
            break;
7,686✔
742
        case TRICK_OPAQUE_TYPE:
×
743
            chkpnt_os << std::endl << "// ERROR - OPAQUE data type (" << attr->type_name << ") cannot be checkpointed." << std::endl;
×
744
            message_publish(MSG_ERROR, "Checkpoint Agent ERROR: OPAQUE data type (%s) cannot be checkpointed.\n", attr->type_name) ;
×
UNCOV
745
        break;
×
UNCOV
746
        default:
×
UNCOV
747
            chkpnt_os << "0";
×
UNCOV
748
            message_publish(MSG_ERROR, "Checkpoint Agent file %s: Unhandled Type (%d).\n", __FILE__, attr->type) ;
×
UNCOV
749
            break;
×
750
    }
751
}
28,749✔
752

753
// MEMBER FUNCTION
754
// Get the variable-name associated with the given variable-address and data-type.
755
// If no data-type is specified, (i.e., if attr == NULL), then the name will refer
756
// to the (inner-most) primitive data-type associated with the address.
757

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

761
std::string Trick::ClassicCheckPointAgent::
960✔
762
    ref_string_from_ptr( void* pointer, ATTRIBUTES* attr, int curr_dim) {
763

764
    std::string reference_string;
1,920✔
765

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

770
    if (pointer == NULL) {
960✔
UNCOV
771
        reference_string = "NULL";
×
772
    } else {
773
        ALLOC_INFO *alloc_info;
774

775
        /** Find the allocation that contains the pointer-address. */
776
        alloc_info = mem_mgr->get_alloc_info_of( pointer);
960✔
777

778
        if (alloc_info != NULL) {
960✔
779
            int alloc_elem_size;
780
            int alloc_elem_index;
781
            int misalignment;
782

783
            alloc_elem_size = alloc_info->size;
925✔
784
            alloc_elem_index = (int) (((long) pointer - (long) alloc_info->start) / alloc_elem_size);
925✔
785
            misalignment = (int) (((long) pointer - (long) alloc_info->start) % alloc_elem_size);
925✔
786

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

791
            if ( (attr != NULL) && (attr->type == alloc_info->type) &&
925✔
792
                 ( (attr->type != TRICK_STRUCTURED) || (attr->attr == alloc_info->attr))) {
913✔
793

794
                int ii;
795
                int n_l_ptrs, n_r_ptrs;
796

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

800
                // Calculate the number of pointers (asterisks) on the right side of the assignment.
801
                n_r_ptrs = 0;
350✔
802
                for (ii=0 ; ii <alloc_info->num_index ; ii++) {
674✔
803
                    if (alloc_info->index[ii] == 0) n_r_ptrs++;
324✔
804
                }
805

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

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

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

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

870
                    if (misalignment == 0) {
1✔
871
                        std::stringstream workss;
2✔
872

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

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

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

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

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

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

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

929
        write_singleton( chkpnt_os, address, attr, offset);
28,749✔
930

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

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

938
            void* pointer = *(void**)((char*)address + offset * sizeof(void*));
951✔
939

940
            ref_string = ref_string_from_ptr( pointer, attr, curr_dim);
951✔
941

942
            chkpnt_os << ref_string.c_str() ;
951✔
943

944
        } else { // Fixed dimension
945

946
            char* src_addr;
947

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

952
                int use_quoted_string;
953

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

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

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

974

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

983

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

986
                    write_quoted_str(chkpnt_os, src_addr);
314✔
987

988
                } else {
989

990
                    int ii, jj;
991
                    int array_len;
992

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

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

998
                    chkpnt_os << "\n";
2,346✔
999

1000
                    for (ii=0 ; ii < curr_dim+1 ; ii++) {
4,697✔
1001
                        chkpnt_os << "    ";
2,351✔
1002
                    }
1003
                    chkpnt_os << "{";
2,346✔
1004

1005
                    for (ii = 0; ii < array_len ; ii++ ) {
8,605✔
1006

1007
                        if (ii > 0) {
6,259✔
1008
                            chkpnt_os << ", ";
3,913✔
1009

1010
                            // Conditionally line-break and indent.
1011
                            if (( (ii+1) % array_elements_per_line[attr->type]) == 0 ) {
3,913✔
1012
                                // Line-break.
1013
                                chkpnt_os << "\n";
301✔
1014
                                // Indent.
1015
                                for (jj=0 ; jj < curr_dim+1 ; jj++) {
602✔
1016
                                    chkpnt_os << "    ";
301✔
1017
                                }
1018
                                chkpnt_os << " ";
301✔
1019
                            }
1020
                        }
1021
                        write_rvalue( chkpnt_os, address, attr, curr_dim + 1, offset * attr->index[curr_dim].size + ii);
6,259✔
1022
                    }
1023
                    chkpnt_os << "}";
2,346✔
1024

1025
                }
2,660✔
1026

1027
            } else { // Not the final fixed dimension.
1028

1029
                int ii;
1030

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

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

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

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

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

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

UNCOV
1059
        return;
×
1060
    }
1061
}
1062

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

1067
    std::string lname = left_side_name();
58,880✔
1068

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

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

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

1089
    if (!input_perm_check(attr)) {
28,226✔
1090
        chkpnt_os << "/* OUTPUT-ONLY: ";
22✔
1091
    }
1092
    if ( attr->type == TRICK_STL ) {
28,226✔
1093
        chkpnt_os << "// STL: " << lname ;
2,382✔
1094
    } else {
1095
        chkpnt_os << lname << " = ";
25,844✔
1096

1097
        write_rvalue( chkpnt_os, (void*)address, attr, curr_dim, offset);
25,844✔
1098
        chkpnt_os << ";";
25,844✔
1099

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

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

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

1113
            // Restore hexfloat setting
UNCOV
1114
            hexfloat_checkpoint = saved_hexfloat;
×
1115

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

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