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

nasa / trick / 18882558702

28 Oct 2025 04:50PM UTC coverage: 55.832% (+0.03%) from 55.8%
18882558702

Pull #1980

github

web-flow
Merge 157cb9992 into cad341798
Pull Request #1980: Don't use TMM to allocate argv

37 of 45 new or added lines in 2 files covered. (82.22%)

113 existing lines in 1 file now uncovered.

12417 of 22240 relevant lines covered (55.83%)

266553.16 hits per line

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

68.37
/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,623✔
62
    return (attr->io & TRICK_CHKPNT_INPUT) ;
113,623✔
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,145✔
71

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

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

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

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

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

86
            case ELEM_NAME: {
59,152✔
87
                name += '.' + element.name;
59,152✔
88
            } break;
59,152✔
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,290✔
104
}
105

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

109
    const char *type_spec;
110

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

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

117
    if ( info->num_index == 0 ) {
2,501✔
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,408✔
122
        int ii;
123

124
        chkpnt_os << type_spec;
2,408✔
125

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

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

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

141
    } else {
142
        // ERROR - num_index cant be negative.
143
    }
144
}
2,501✔
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
        /* if left_type specifies the current member, stop here */
326
        if ( (left_type != NULL) && (*left_type != NULL) && (Ai->attr == (*left_type)->attr)) {
131✔
UNCOV
327
            return 0;
×
328
        }
329

330
        char buf[256];
331
        ret = getCompositeSubReference( rAddr, left_type, sAddr + Ai->offset, (ATTRIBUTES *) Ai->attr, buf);
131✔
332

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

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

348
/*********** Member is an arrayed struct **************************************/ 
349

350
    offset = (long) rAddr - ((long) sAddr + Ai->offset);
1✔
351
    size = last_size = Ai->size;
1✔
352

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

363

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

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

375
/**** Go find the subreference for the arrayed struct member and append *********/
376

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

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

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

400
    return 0;
1✔
401
}
402

403

404
// MEMBER FUNCTION
405
// Get the fully qualified varible name of the Allocation, given the address.
406

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

416
    var_name = name;
543✔
417
    ret = getCompositeSubReference( addr, left_type, struct_addr, A, reference_name );
543✔
418

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

430
// MEMBER FUNCTION
431
int Trick::ClassicCheckPointAgent::restore( std::istream* checkpoint_stream) {
22✔
432

433
    ChkPtParseContext* context = new ChkPtParseContext( mem_mgr, checkpoint_stream);
22✔
434
    int status = 0;
22✔
435

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

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

458
// MEMBER FUNCTION
459
int Trick::ClassicCheckPointAgent::is_nil_valued( void* address,
63,836✔
460
                                                  ATTRIBUTES* attr,
461
                                                  int curr_dim,
462
                                                  int offset
463
                                                ) {
464

465
    char* test_addr;
466
    int remaining_dimensions = attr->num_index - curr_dim;
63,836✔
467

468
    /** @par Detailed Description: */
469

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

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

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

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

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

591
           for (ii=0; ii < curr_dim_size; ii++) {
8,817✔
592
               zerotest = is_nil_valued( address, attr, curr_dim+1, offset*curr_dim_size+ii);
8,691✔
593
               if (!(zerotest == 1)) return(zerotest);
8,691✔
594
           }
595
           return(1);
126✔
596
       }
597

598
    } else {
UNCOV
599
        return(-1);
×
600
    }
601
    return(0);
825✔
602
}
603

604
// STATIC FUNCTION
605
static void write_quoted_str( std::ostream& os, const char* s) {
7,565✔
606
    int ii;
607
    int len = strlen(s);
7,565✔
608
    os << "\"" ;
7,565✔
609
    for (ii=0 ; ii<len ; ii++) {
131,537✔
610
        switch ((s)[ii]) {
123,972✔
611
        case '\n': os << "\\n"; break;
54✔
UNCOV
612
        case '\t': os << "\\t"; break;
×
UNCOV
613
        case '\b': os << "\\b"; break;
×
614
        case '\"': os << "\\\""; break;
62✔
615
        default  : os << s[ii] ; break;
123,856✔
616
        }
617
    }
618
    os << "\"" ;
7,565✔
619
}
7,565✔
620

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

623
    void* src_addr;
624

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

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

684
                enum_attr = (ENUM_ATTR*)attr->attr;
80✔
685

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

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

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

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

813
std::string Trick::ClassicCheckPointAgent::
920✔
814
    ref_string_from_ptr( void* pointer, ATTRIBUTES* attr, int curr_dim) {
815

816
    std::string reference_string;
1,840✔
817

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

822
    if (pointer == NULL) {
920✔
UNCOV
823
        reference_string = "NULL";
×
824
    } else {
825
        ALLOC_INFO *alloc_info;
826

827
        /** Find the allocation that contains the pointer-address. */
828
        alloc_info = mem_mgr->get_alloc_info_of( pointer);
920✔
829

830
        if (alloc_info != NULL) {
920✔
831
            int alloc_elem_size;
832
            int alloc_elem_index;
833
            int misalignment;
834

835
            alloc_elem_size = alloc_info->size;
887✔
836
            alloc_elem_index = (int) (((long) pointer - (long) alloc_info->start) / alloc_elem_size);
887✔
837
            misalignment = (int) (((long) pointer - (long) alloc_info->start) % alloc_elem_size);
887✔
838

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

843
            if ( (attr != NULL) && (attr->type == alloc_info->type) &&
887✔
844
                 ( (attr->type != TRICK_STRUCTURED) || (attr->attr == alloc_info->attr))) {
875✔
845

846
                int ii;
847
                int n_l_ptrs, n_r_ptrs;
848

849
                // Calculate the number of pointers (asterisks) on the left side of the assignment.
850
                n_l_ptrs = attr->num_index - curr_dim;
343✔
851

852
                // Calculate the number of pointers (asterisks) on the right side of the assignment.
853
                n_r_ptrs = 0;
343✔
854
                for (ii=0 ; ii <alloc_info->num_index ; ii++) {
660✔
855
                    if (alloc_info->index[ii] == 0) n_r_ptrs++;
317✔
856
                }
857

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

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

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

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

922
                    if (misalignment == 0) {
1✔
923
                        std::stringstream workss;
2✔
924

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

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

948
            }
949
        } else if ((attr != NULL) && ((curr_dim + 1) == attr->num_index)) {
33✔
950

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

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

975
// MEMBER FUNCTION
976
void Trick::ClassicCheckPointAgent::write_rvalue( std::ostream& chkpnt_os, void* address, ATTRIBUTES* attr, int curr_dim, int offset) {
30,478✔
977

978
    // If the variable that we are pointing to is Un-arrayed
979
    if (curr_dim == attr->num_index) {
30,478✔
980

981
        write_singleton( chkpnt_os, address, attr, offset);
27,033✔
982

983
    // If the variable that we are pointing to is Arrayed
984
    } else if (curr_dim < attr->num_index) {
3,445✔
985

986
        // If the variable is a pointer
987
        if (attr->index[curr_dim].size == 0) {
3,445✔
988
            std::string ref_string;
1,822✔
989

990
            void* pointer = *(void**)((char*)address + offset * sizeof(void*));
911✔
991

992
            ref_string = ref_string_from_ptr( pointer, attr, curr_dim);
911✔
993

994
            chkpnt_os << ref_string.c_str() ;
911✔
995

996
        } else { // Fixed dimension
997

998
            char* src_addr;
999

1000
            // If this is the final, fixed dimension
1001
            if (((curr_dim + 1) == attr->num_index) ||
2,534✔
1002
                (attr->index[curr_dim + 1].size == 0)) {
45✔
1003

1004
                int use_quoted_string;
1005

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

1010
                use_quoted_string = 1;
2,530✔
1011
                if (attr->type == TRICK_CHARACTER) {
2,530✔
1012

1013
                    int array_len = attr->index[curr_dim].size;
365✔
1014
                    int ii = array_len - 1;
365✔
1015
                    src_addr = (char*)address + offset * array_len * sizeof(char);
365✔
1016
                    if (src_addr[ii] != '\0') {
365✔
1017
                        use_quoted_string = 0;
18✔
1018
                    }
1019
                    ii--;
365✔
1020
                    while ( use_quoted_string && (ii >= 0) ) {
2,614✔
1021
                        use_quoted_string = isprint( src_addr[ii]);
2,249✔
1022
                        ii--;
2,249✔
1023
                    }
1024
                }
1025

1026

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

1035

1036
                if ((attr->type == TRICK_CHARACTER) && use_quoted_string)  {
2,530✔
1037

1038
                    write_quoted_str(chkpnt_os, src_addr);
313✔
1039

1040
                } else {
1041

1042
                    int ii, jj;
1043
                    int array_len;
1044

1045
                    // Determine the number of array elements we need to print out
1046
                    // to get all of the non-zero values.
1047

1048
                    array_len = attr->index[curr_dim].size ;
2,217✔
1049

1050
                    chkpnt_os << "\n";
2,217✔
1051

1052
                    for (ii=0 ; ii < curr_dim+1 ; ii++) {
4,439✔
1053
                        chkpnt_os << "    ";
2,222✔
1054
                    }
1055
                    chkpnt_os << "{";
2,217✔
1056

1057
                    for (ii = 0; ii < array_len ; ii++ ) {
8,284✔
1058

1059
                        if (ii > 0) {
6,067✔
1060
                            chkpnt_os << ", ";
3,850✔
1061

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

1077
                }
2,530✔
1078

1079
            } else { // Not the final fixed dimension.
1080

1081
                int ii;
1082

1083
                chkpnt_os << "\n";
4✔
1084
                for (ii=0 ; ii < curr_dim+1 ; ii++) {
8✔
1085
                    chkpnt_os << "    ";
4✔
1086
                }
1087
                chkpnt_os << "{";
4✔
1088

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

1096
                chkpnt_os << "\n";
4✔
1097

1098
                for (ii=0 ; ii < curr_dim+1 ; ii++) {
8✔
1099
                    chkpnt_os << "    " ;
4✔
1100
                }
1101
                chkpnt_os << "}";
4✔
1102
            }
1103
        }
1104

1105
    } else {
1106
        chkpnt_os << "/*ERROR*/";
×
1107

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

UNCOV
1111
        return;
×
1112
    }
1113
}
1114

1115
// MEMBER FUNCTION
1116
// Create an assignment statement.
1117
void Trick::ClassicCheckPointAgent::assign_rvalue(std::ostream& chkpnt_os, void* address, ATTRIBUTES* attr, int curr_dim, int offset) {
55,145✔
1118

1119
    std::string lname = left_side_name();
55,145✔
1120

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

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

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

1141
    if (!input_perm_check(attr)) {
26,338✔
1142
        chkpnt_os << "/* OUTPUT-ONLY: ";
21✔
1143
    }
1144
    if ( attr->type == TRICK_STL ) {
26,338✔
1145
        chkpnt_os << "// STL: " << lname ;
2,188✔
1146
    } else {
1147
        chkpnt_os << lname << " = ";
24,150✔
1148

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

1152
        // Check if we need to add decimal comments for hexfloat values
1153
        bool should_add_decimal_comment = hexfloat_decimal_comment_checkpoint && hexfloat_checkpoint && (attr->type == TRICK_FLOAT || attr->type == TRICK_DOUBLE);
24,150✔
1154

1155
        // Add decimal comment for hexfloat values
1156
        if (should_add_decimal_comment) {
24,150✔
1157
            // Temporarily disable hexfloat to get decimal representation
1158
            bool saved_hexfloat = hexfloat_checkpoint;
×
UNCOV
1159
            hexfloat_checkpoint = false;
×
1160

1161
            // Capture decimal output to string stream
UNCOV
1162
            std::stringstream decimal_ss;
×
UNCOV
1163
            write_rvalue( decimal_ss, (void*)address, attr, curr_dim, offset);
×
1164

1165
            // Restore hexfloat setting
1166
            hexfloat_checkpoint = saved_hexfloat;
×
1167

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

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