C test format

Overview

In order to facilitate the task of specifying tests to be reproduced/generated by Microprobe, we defined a C code environment so that the users can write down the test cases in C, and then let the compiler and the Microprobe framework to perform the code generation and all the plumbing required to make it work.

In brief, besides the actual implementation of the test case main function (named c2mpt_function), the user has to define a set of C macros so that the framework knows which variables and functions should also be included in the generated MPT. Optionally, the user can also define an initialization function, which will be called before the test case main function, to initialize the data values. The following sections explain more details about this environment.

Variable declaration and registration

The variables have to be declared and registered using a set of macros provided by the C test environment (defined in c2mpt.h file shown below). This allows the environment to know which variables are required to be part of the generated MPT.

The following macros are defined to declare variables:

  • DECLARE_VARIABLE(type, name, alignment)

  • DECLARE_VARIABLE_WITH_VALUE(type, name, alignment, init_value)

  • DECLARE_VARIABLE_ARRAY(type, name, name+dimension, alignment)

  • DECLARE_VARIABLE_ARRAY_WITH_VALUE(type, name, name+dimension alignment, init_value)

where:

  • type: is the variable type (e.g. char)

  • name: is the variable name (e.g. myvar)

  • name+dimension: is the name of the array and the dimensions of the array (e.g. myvar[10][20] )

  • alignment: is the minimum alignment for the variable

  • init_value: is the initial value

The following macros are defined to register the variables:

  • BEGIN_VARIABLE_REGISTRATION

  • REGISTER_VARIABLE(name)

  • END_VARIABLE_REGISTRATION

where:

  • name: is the variable name to register

Function registration

Besides the variables, the functions that need to be placed in the generated MPT also have to be declared using special macros. Instead of using regular fname(type1 arg1, type2 arg2,  ...  , type3 arg3) function signature declarations, the declarations should of the form MPT_FUNCTION(fname(type1 arg1, type2 arg2,  ...  , type3 arg3)). That is, just wrap the function signatures using the MPT_FUNCTION macro.

Function implementation

After defining how to declare variables and define function signatures, one needs to provide the implementation of the following function:

  • void c2mpt_function() : This is the main test function, which will be converted to the MPT format. This function can not perform library calls and it only should access to local variables (that will be placed in the stack) or global MPT register variables.

  • void c2mpt_init_global_vars() (optional): Use this function to initialize any global variables registered to the MPT. This function, since it is not going to be included in the generate MPT, can call any other functions and does not have any restriction.

  • Any other subroutine called by the c2mpt_function. Again, these subroutines, like the c2mpt_function can not perform library calls or access to global variables not registered in the MPT environment.

Examples

A matrix multiply example:

  1#include "c2mpt.h"
  2
  3/****************************************************************************/
  4// Global variables
  5//
  6// Define in the section below the global variable to be used in the 
  7// "c2mpt_function" and its subroutines. Variable below are going to be
  8// imported to the mpt format. The variables have to be declared first
  9// and then, they have to be registered (see example below).
 10//
 11// The following macros are defined to declare variables:
 12//
 13// DECLARE_VARIABLE(type, name, alignment)
 14// DECLARE_VARIABLE_WITH_VALUE(type, name, alignment, init_value)
 15// DECLARE_VARIABLE_ARRAY(type, name, name+dimension, alignment)
 16// DECLARE_VARIABLE_ARRAY_WITH_VALUE(type, name, name+dimension alignment, init_value)
 17//
 18// where:
 19//
 20// - type: is the variable type (e.g. char)
 21// - name: is the variable name (e.g. myvar)
 22// - name+dimension: is the name of the array and the dimensions of the array 
 23//                   (e.g. myvar[10][20] )
 24// - alignment: is the minimum algnment for the variable                 
 25// - init_value: is the initial value
 26//
 27// The following macros are defined to register the variables:
 28//
 29// BEGIN_VARIABLE_REGISTRATION
 30// REGISTER_VARIABLE(name)
 31// END_VARIABLE_REGISTRATION
 32//
 33// where:
 34//
 35// - name: is the variable name to register
 36//
 37/****************************************************************************/
 38
 39#define N 10
 40
 41DECLARE_VARIABLE_ARRAY(int64_t,matA,matA[N][N],sizeof(int64_t))
 42DECLARE_VARIABLE_ARRAY(int64_t,matB,matB[N][N],sizeof(int64_t))
 43DECLARE_VARIABLE_ARRAY_WITH_VALUE(int64_t,matC,matC[N][N],sizeof(int64_t), {[0][1]=2,[1][0]=1} )
 44
 45BEGIN_VARIABLE_REGISTRATION
 46REGISTER_VARIABLE(matA)
 47REGISTER_VARIABLE(matB)
 48REGISTER_VARIABLE(matC)
 49END_VARIABLE_REGISTRATION
 50
 51/****************************************************************************/
 52// Function declaration 
 53//
 54// Declare the functions to be converted to the MPT format. It is mandatory 
 55// to define a "c2mpt_function", which will be the "main" of the test. Also
 56// include any related subroutines. The related subroutines have to be
 57// defined using the MPT_FUNCTION(signature) macro provided.
 58//
 59// The function signature for the main c2mpt_function should not be modified.
 60// It does not have any parameter. One can use global variables to pass parameters
 61// to the function (see the example).
 62//
 63/****************************************************************************/
 64
 65MPT_FUNCTION(int64_t my_subroutine(int64_t X, int64_t Y, int64_t Z))
 66
 67/****************************************************************************/
 68// Function implementation
 69//
 70// Include below the implementation of the routines defined above, which
 71// should be included in the mpt. They should not call functions not defined 
 72// here because the test should be self-contained to be reproduced safely.
 73//
 74// Remember to defined the "c2mpt_function" main function.
 75//
 76/****************************************************************************/
 77
 78int64_t __attribute__ ((noinline)) my_subroutine(int64_t X, int64_t Y, int64_t Z)
 79{
 80    return Z + (X * Y);
 81}
 82
 83void c2mpt_function()
 84{
 85    int i,j,k;
 86
 87    for(i=0;i<N;i++){
 88        for(j=0;j<N;j++){
 89            matC[i][j]=0;
 90            for(k=0;k<N;k++){
 91                matC[i][j]=my_subroutine(matA[i][k], matB[k][j], matC[i][j]);
 92            }
 93        }
 94    }
 95}
 96
 97
 98/****************************************************************************/
 99// Initialization function 
100//
101// In case you need to initialize the global variables, you can do that in
102// the function below. This function can use any external function
103// including IO (e.g. reading values from disk) . This function will not
104// be included the mpt.
105//
106// If you initialize variable pointers, they should point to addresses of 
107// variables defined to be included in the MPT.
108// 
109/****************************************************************************/
110
111void c2mpt_init_global_vars()
112{ 
113    for(int i=0; i < N; i++){
114        for(int j=0; j < N; j++){
115            matA[i][j] = i;
116            matB[i][j] = j;
117            matC[i][j] = i+j;
118        }
119    }
120}
121

A linked list code example:

  1#include "c2mpt.h"
  2
  3/****************************************************************************/
  4// Global variables
  5//
  6// Define in the section below the global variable to be used in the 
  7// "c2mpt_function" and its subroutines. Variable below are going to be
  8// imported to the mpt format. The variables have to be declared first
  9// and then, they have to be registered (see example below).
 10//
 11// The following macros are defined to declare variables:
 12//
 13// DECLARE_VARIABLE(type, name, alignment)
 14// DECLARE_VARIABLE_WITH_VALUE(type, name, alignment, init_value)
 15// DECLARE_VARIABLE_ARRAY(type, name, name+dimension, alignment)
 16// DECLARE_VARIABLE_ARRAY_WITH_VALUE(type, name, name+dimension alignment, init_value)
 17//
 18// where:
 19//
 20// - type: is the variable type (e.g. char)
 21// - name: is the variable name (e.g. myvar)
 22// - name+dimension: is the name of the array and the dimensions of the array 
 23//                   (e.g. myvar[10][20] )
 24// - alignment: is the minimum algnment for the variable                 
 25// - init_value: is the initial value
 26//
 27// The following macros are defined to register the variables:
 28//
 29// BEGIN_VARIABLE_REGISTRATION
 30// REGISTER_VARIABLE(name)
 31// END_VARIABLE_REGISTRATION
 32//
 33// where:
 34//
 35// - name: is the variable name to register
 36//
 37/****************************************************************************/
 38
 39#define N 5
 40
 41struct node {
 42      int64_t x;
 43      struct node *next;
 44};
 45
 46typedef struct node node_t;
 47node_t array[N];
 48
 49DECLARE_VARIABLE_ARRAY(node_t,linkedlist,linkedlist[N],sizeof(node_t))
 50DECLARE_VARIABLE_WITH_VALUE(int64_t,count,sizeof(int64_t), 0xCAFECAFE)
 51
 52BEGIN_VARIABLE_REGISTRATION
 53REGISTER_VARIABLE(count)
 54REGISTER_VARIABLE(linkedlist)
 55END_VARIABLE_REGISTRATION
 56
 57/****************************************************************************/
 58// Function declaration 
 59//
 60// Declare the functions to be converted to the MPT format. It is mandatory 
 61// to define a "c2mpt_function", which will be the "main" of the test. Also
 62// include any related subroutines. The related subroutines have to be
 63// defined using the MPT_FUNCTION(signature) macro provided.
 64//
 65// The function signature for the main c2mpt_function should not be modified.
 66// It does not have any parameter. One can use global variables to pass parameters
 67// to the function (see the example).
 68//
 69/****************************************************************************/
 70
 71MPT_FUNCTION(void my_subroutine(int64_t count))
 72
 73/****************************************************************************/
 74// Function implementation
 75//
 76// Include below the implementation of the routines defined above, which
 77// should be included in the mpt. They should not call functions not defined 
 78// here because the test should be self-contained to be reproduced safely.
 79//
 80// Remember to defined the "c2mpt_function" main function.
 81//
 82/****************************************************************************/
 83
 84void c2mpt_function()
 85{
 86
 87    node_t* node = & linkedlist[0];
 88    while(node->next != NULL)
 89    {
 90        node = node->next;
 91        count += node->x;
 92    }
 93
 94    my_subroutine(count);
 95
 96}
 97
 98void my_subroutine(int64_t lcount)
 99{
100    count=lcount+lcount;
101}
102
103/****************************************************************************/
104// Initialization function 
105//
106// In case you need to initialize the global variables, you can do that in
107// the function below. This function can use any external function
108// including IO (e.g. reading values from disk) . This function will not
109// be included the mpt.
110//
111// If you initialize variable pointers, they should point to addresses of 
112// variables defined to be included in the MPT.
113// 
114/****************************************************************************/
115
116void c2mpt_init_global_vars()
117{ 
118    for(int i=0; i < N; i++){
119        linkedlist[i].x = 0x0102030405060708;
120       
121        if(i<N-1)
122        {
123            linkedlist[i].next = &(linkedlist[i+1]);
124        }
125        else
126        {
127            linkedlist[i].next = NULL;
128        }
129    }
130}
131

Template

Copy and paste the following template (or use the --dump-c2mpt-template flag to get it) to start editing an empty C test format:

  1#include "c2mpt.h"
  2
  3/****************************************************************************/
  4// Global variables
  5//
  6// Define in the section below the global variable to be used in the 
  7// "c2mpt_function" and its subroutines. Variables below are going to be
  8// imported to the mpt format. The variables have to be declared first
  9// and then they have to be registered (see example below).
 10//
 11// The following macros are defined to declare variables:
 12//
 13// DECLARE_VARIABLE(type, name, alignment)
 14// DECLARE_VARIABLE_WITH_VALUE(type, name, alignment, init_value)
 15// DECLARE_VARIABLE_ARRAY(type, name, name+dimension, alignment)
 16// DECLARE_VARIABLE_ARRAY_WITH_VALUE(type, name, name+dimension alignment, init_value)
 17//
 18// where:
 19//
 20// - type: is the variable type (e.g. char)
 21// - name: is the variable name (e.g. myvar)
 22// - name+dimension: is the name of the array and the dimensions of the array 
 23//                   (e.g. myvar[10][20] )
 24// - alignment: is the minimum algnment for the variable                 
 25// - init_value: is the initial value
 26//
 27// The following macros are defined to register the variables:
 28//
 29// BEGIN_VARIABLE_REGISTRATION
 30// REGISTER_VARIABLE(name)
 31// END_VARIABLE_REGISTRATION
 32//
 33// where:
 34//
 35// - name: is the variable name to register
 36//
 37// Example:
 38//
 39// #define N 10
 40//
 41// DECLARE_VARIABLE_ARRAY(int64_t,matA,matA[N][N],sizeof(int64_t))
 42// DECLARE_VARIABLE_ARRAY(int64_t,matB,matB[N][N],sizeof(int64_t))
 43// DECLARE_VARIABLE_ARRAY_WITH_VALUE(int64_t,matC,matC[N][N],sizeof(int64_t),
 44//                                   {[0][1]=2,[1][0]=1} )
 45//
 46// BEGIN_VARIABLE_REGISTRATION
 47// REGISTER_VARIABLE(matA)
 48// REGISTER_VARIABLE(matB)
 49// REGISTER_VARIABLE(matC)
 50// END_VARIABLE_REGISTRATION
 51//
 52/****************************************************************************/
 53
 54<< DECLARE AND REGISTER YOUR VARIABLES HERE >>
 55
 56/****************************************************************************/
 57// Subroutine declaration 
 58//
 59// Declare any subroutine to be included in the MPT generated using the 
 60// MPT_FUNCTION(signature) macro provided.
 61//
 62// Example:
 63//
 64// MPT_FUNCTION(int64_t my_subroutine(int64_t X, int64_t Y, int64_t Z))
 65//
 66/****************************************************************************/
 67
 68<< DECLARE YOUR SUBROUTINES HERE >>
 69
 70/****************************************************************************/
 71// Function implementation
 72//
 73// Include below the implementation of the routines defined above, which
 74// will be included in the MPT. They should not call functions that will not 
 75// be included in the MPT. That is, only call functions declared using the 
 76// MPT_FUNCTION macro.
 77//
 78// Remember to implement the "c2mpt_function", which will be the main test
 79// function.
 80//
 81/****************************************************************************/
 82
 83void c2mpt_function()
 84{
 85
 86    << IMPLEMENT THE MAIN FUNCTION HERE >>
 87
 88}
 89
 90<< IMPLEMENT ANY SUBROUTINES HERE >>
 91
 92/****************************************************************************/
 93// Initialization function 
 94//
 95// In case you need to initialize the global variables, you can do that in
 96// the function below. This function can use any external function
 97// including IO (e.g. reading values from disk) . This function will not
 98// be included the MPT generated.
 99//
100// If you initialize variable pointers, they should point to addresses of 
101// variables defined to be included in the MPT.
102// 
103/****************************************************************************/
104
105void c2mpt_init_global_vars()
106{ 
107
108    << INITIALIZE THE GLOBAL VARIABLES HERE >>
109    
110}
111

Implementation details

The following two files are compiled along the C test file provided as input by the user. Check them to understand the implementation details in case you want to debug the functionality:

 1#include <stdlib.h>
 2#include <stdio.h>
 3#include <stdint.h>
 4#include <inttypes.h>
 5#include <strings.h>
 6#include <string.h>
 7#include <assert.h>
 8
 9typedef struct c2mpt_var {           
10    char vartype[50];        
11    char varname[50];       
12    void * address;                
13    uint_fast64_t nelems;         
14    uint_fast64_t elems_size;    
15    uint_fast64_t alignment;    
16} c2mpt_var ;                  
17
18void c2mpt_dump_data(void);
19
20#define DECLARE_VARIABLE_ARRAY(type,name,array,alignment)                      \
21    type array                                                                 \
22        __attribute__ ((section ("microprobe.data")))                          \
23        __attribute__ ((aligned (alignment)))                                  \
24    ;                                                                          \
25    c2mpt_var c2mpt_var_##name = { #type, #name,                               \
26                                 (void * ) & name[0],                          \
27                                        sizeof(name)/                          \
28                                     sizeof(type),                             \
29                                          alignment }; 
30
31#define DECLARE_VARIABLE_ARRAY_WITH_VALUE(type,name,array,alignment, ...)      \
32    type array                                                                 \
33        __attribute__ ((section ("microprobe.data")))                          \
34        __attribute__ ((aligned (alignment)))                                  \
35    = __VA_ARGS__;                                                             \
36    c2mpt_var c2mpt_var_##name = { #type, #name,                               \
37                                 (void * ) & name[0],                          \
38                                        sizeof(name)/                          \
39                                     sizeof(type),                             \
40                                          alignment }; 
41
42#define DECLARE_VARIABLE(type,name,alignment)                                  \
43    type name                                                                  \
44        __attribute__ ((section ("microprobe.data")))                          \
45        __attribute__ ((aligned (alignment)))                                  \
46    ;                                                                          \
47    c2mpt_var c2mpt_var_##name = { #type, #name,                               \
48                                 (void * ) & name, 1,                          \
49                                         sizeof(name),                         \
50                                          alignment }; 
51
52#define DECLARE_VARIABLE_WITH_VALUE(type,name,alignment, value)                \
53    type name                                                                  \
54        __attribute__ ((section ("microprobe.data")))                          \
55        __attribute__ ((aligned (alignment)))                                  \
56    = value;                                                                   \
57    c2mpt_var c2mpt_var_##name = { #type, #name,                               \
58                                 (void * ) & name, 1,                          \
59                                         sizeof(name),                         \
60                                          alignment }; 
61
62#define BEGIN_VARIABLE_REGISTRATION                                            \
63    c2mpt_var* c2mpt_vars[] = {                        
64
65#define REGISTER_VARIABLE(name) &c2mpt_var_##name,
66        
67#define END_VARIABLE_REGISTRATION                                              \
68    };                                                                         \
69    extern void c2mpt_dump_var(c2mpt_var var);                                 \
70    MPT_DUMP_FUNCTION 
71    
72#define MPT_FUNCTION(signature)                                                \
73    signature                                                                  \
74    __attribute__ ((section ("microprobe.text")));
75
76MPT_FUNCTION(void c2mpt_function(void))
77
78#define MPT_DUMP_FUNCTION                                                      \
79    void c2mpt_dump_data(void)                                                 \
80    {                                                                          \
81        uint_fast64_t i = 0;                                                   \
82        uint_fast64_t nvars = 0;                                               \
83        nvars = sizeof(c2mpt_vars) / sizeof(c2mpt_vars[0]);                    \
84        for(i=0; i < nvars; i++)                                               \
85        {                                                                      \
86            c2mpt_dump_var(*(c2mpt_vars[i]));                                  \
87        }                                                                      \
88    }                                                                          \
89
90#ifndef MPT_BASE_ADDRESS
91    #define MPT_BASE_ADDRESS 0x0
92#endif
  1#include "c2mpt.h"
  2
  3extern c2mpt_var* c2mpt_vars; 
  4extern void c2mpt_function(void);
  5extern void c2mpt_dump_data(void);
  6extern void c2mpt_init_global_vars(void);
  7
  8/****************************************************************************/
  9// Dump data functions
 10/****************************************************************************/
 11
 12void c2mpt_print_value(void * value, uint_fast64_t size, char* vartype)
 13{
 14    // pointers
 15    if(index(vartype, '*') != NULL)
 16    {
 17        assert(size == sizeof(void *));
 18        printf("%p", value);
 19    }
 20    // C generic data types
 21    else if(strcasecmp(vartype, "char") == 0)
 22    {
 23        assert(size == sizeof(char));
 24        printf("%hhu", *((char *) value));
 25    }
 26    else if(strcasecmp(vartype, "signed char") == 0)
 27    {
 28        assert(size == sizeof(signed char));
 29        printf("%hhi", *((signed char *) value));
 30    }
 31    else if(strcasecmp(vartype, "unsigned char") == 0)
 32    {
 33        assert(size == sizeof(unsigned char));
 34        printf("%hhu", *((unsigned char *) value));
 35    }
 36    else if(strcasecmp(vartype, "short") == 0)
 37    {
 38        assert(size == sizeof(short));
 39        printf("%hi", *((short *) value));
 40    }
 41    else if(strcasecmp(vartype, "short int") == 0)
 42    {
 43        assert(size == sizeof(short int));
 44        printf("%hi", *((short int *) value));
 45    }
 46    else if(strcasecmp(vartype, "signed short") == 0)
 47    {
 48        assert(size == sizeof(signed short));
 49        printf("%hi", *((signed short *) value));
 50    }
 51    else if(strcasecmp(vartype, "signed short int") == 0)
 52    {
 53        assert(size == sizeof(signed short int));
 54        printf("%hi", *((signed short int *) value));
 55    }
 56    else if(strcasecmp(vartype, "unsigned short") == 0)
 57    {
 58        assert(size == sizeof(unsigned short));
 59        printf("%hu", *((unsigned short *) value));
 60    }
 61    else if(strcasecmp(vartype, "unsigned short int") == 0)
 62    {
 63        assert(size == sizeof(unsigned short int));
 64        printf("%hu", *((unsigned short int *) value));
 65    }
 66    else if(strcasecmp(vartype, "int") == 0)
 67    {
 68        assert(size == sizeof(int));
 69        printf("%d", *((int *) value));
 70    }
 71    else if(strcasecmp(vartype, "signed") == 0)
 72    {
 73        assert(size == sizeof(signed));
 74        printf("%d", *((signed *) value));
 75    }
 76    else if(strcasecmp(vartype, "signed int") == 0)
 77    {
 78        assert(size == sizeof(signed int));
 79        printf("%d", *((signed int *) value));
 80    }
 81    else if(strcasecmp(vartype, "unsigned") == 0)
 82    {
 83        assert(size == sizeof(unsigned));
 84        printf("%u", *((unsigned *) value));
 85    }
 86    else if(strcasecmp(vartype, "unsigned int") == 0)
 87    {
 88        assert(size == sizeof(unsigned int));
 89        printf("%u", *((unsigned int *) value));
 90    }
 91    else if(strcasecmp(vartype, "long") == 0)
 92    {
 93        assert(size == sizeof(long));
 94        printf("%li", *((long *) value));
 95    }
 96    else if(strcasecmp(vartype, "long int") == 0)
 97    {
 98        assert(size == sizeof(long int));
 99        printf("%li", *((long int *) value));
100    }
101    else if(strcasecmp(vartype, "signed long") == 0)
102    {
103        assert(size == sizeof(signed long));
104        printf("%li", *((signed long *) value));
105    }
106    else if(strcasecmp(vartype, "signed long int") == 0)
107    {
108        assert(size == sizeof(signed long int));
109        printf("%li", *((signed long int *) value));
110    }
111    else if(strcasecmp(vartype, "unsigned long") == 0)
112    {
113        assert(size == sizeof(unsigned long));
114        printf("%lu", *((unsigned long *) value));
115    }
116    else if(strcasecmp(vartype, "unsigned long int") == 0)
117    {
118        assert(size == sizeof(unsigned long int));
119        printf("%lu", *((unsigned long int *) value));
120    }
121    else if(strcasecmp(vartype, "long long") == 0)
122    {
123        assert(size == sizeof(long long));
124        printf("%lli", *((long long *) value));
125    }
126    else if(strcasecmp(vartype, "long long int") == 0)
127    {
128        assert(size == sizeof(long long int));
129        printf("%lli", *((long long int *) value));
130    }
131    else if(strcasecmp(vartype, "signed long long") == 0)
132    {
133        assert(size == sizeof(signed long long));
134        printf("%lli", *((signed long long *) value));
135    }
136    else if(strcasecmp(vartype, "signed long long int") == 0)
137    {
138        assert(size == sizeof(signed long long int));
139        printf("%lli", *((signed long long int *) value));
140    }
141    else if(strcasecmp(vartype, "float") == 0)
142    {
143        assert(size == sizeof(float));
144        printf("%f", *((float *) value));
145    }
146    else if(strcasecmp(vartype, "double") == 0)
147    {
148        assert(size == sizeof(double));
149        printf("%f", *((double *) value));
150    }
151    else if(strcasecmp(vartype, "long double") == 0)
152    {
153        assert(size == sizeof(long double));
154        printf("%Lf", *((long double *) value));
155    }
156    // C width fixed data types
157    else if(strcasecmp(vartype, "int8_t") == 0)
158    {
159        assert(size == sizeof(int8_t));
160        printf("%hhi", *((int8_t *) value));
161    }
162    else if(strcasecmp(vartype, "int_least8_t") == 0)
163    {
164        assert(size == sizeof(int_least8_t));
165        printf("%"PRIdLEAST8, *((int_least8_t *) value));
166    }
167    else if(strcasecmp(vartype, "int_fast8_t") == 0)
168    {
169        assert(size == sizeof(int_fast8_t));
170        printf("%"PRIdFAST8, *((int_fast8_t *) value));
171    }
172    else if(strcasecmp(vartype, "uint8_t") == 0)
173    {
174        assert(size == sizeof(uint8_t));
175        printf("%hhu", *((uint8_t *) value));
176    }
177    else if(strcasecmp(vartype, "uint_least8_t") == 0)
178    {
179        assert(size == sizeof(uint_least8_t));
180        printf("%"PRIuLEAST8, *((uint_least8_t *) value));
181    }
182    else if(strcasecmp(vartype, "uint_fast8_t") == 0)
183    {
184        assert(size == sizeof(uint_fast8_t));
185        printf("%"PRIuFAST8, *((uint_fast8_t *) value));
186    }
187    else if(strcasecmp(vartype, "int16_t") == 0)
188    {
189        assert(size == sizeof(int16_t));
190        printf("%hi", *((int16_t *) value));
191    }
192    else if(strcasecmp(vartype, "int_least16_t") == 0)
193    {
194        assert(size == sizeof(int_least16_t));
195        printf("%"PRIdLEAST16, *((int_least16_t *) value));
196    }
197    else if(strcasecmp(vartype, "int_fast16_t") == 0)
198    {
199        assert(size == sizeof(int_fast16_t));
200        printf("%"PRIdFAST16, *((int_fast16_t *) value));
201    }
202    else if(strcasecmp(vartype, "uint16_t") == 0)
203    {
204        assert(size == sizeof(uint16_t));
205        printf("%hu", *((uint16_t *) value));
206    }
207    else if(strcasecmp(vartype, "uint_least16_t") == 0)
208    {
209        assert(size == sizeof(uint_least16_t));
210        printf("%"PRIuLEAST16, *((uint_least16_t *) value));
211    }
212    else if(strcasecmp(vartype, "uint_fast16_t") == 0)
213    {
214        assert(size == sizeof(uint_fast16_t));
215        printf("%"PRIuFAST16, *((uint_fast16_t *) value));
216    }
217    else if(strcasecmp(vartype, "int32_t") == 0)
218    {
219        assert(size == sizeof(int32_t));
220        printf("%d", *((int32_t *) value));
221    }
222    else if(strcasecmp(vartype, "int_least32_t") == 0)
223    {
224        assert(size == sizeof(int_least32_t));
225        printf("%"PRIdLEAST32, *((int_least32_t *) value));
226    }
227    else if(strcasecmp(vartype, "int_fast32_t") == 0)
228    {
229        assert(size == sizeof(int_fast32_t));
230        printf("%"PRIdFAST32, *((int_fast32_t *) value));
231    }
232    else if(strcasecmp(vartype, "uint32_t") == 0)
233    {
234        assert(size == sizeof(uint32_t));
235        printf("%u", *((uint32_t *) value));
236    }
237    else if(strcasecmp(vartype, "uint_least32_t") == 0)
238    {
239        assert(size == sizeof(uint_least32_t));
240        printf("%"PRIuLEAST32, *((uint_least32_t *) value));
241    }
242    else if(strcasecmp(vartype, "uint_fast32_t") == 0)
243    {
244        assert(size == sizeof(uint_fast32_t));
245        printf("%"PRIdFAST32, *((uint_fast32_t *) value));
246    }
247    else if(strcasecmp(vartype, "int64_t") == 0)
248    {
249        assert(size == sizeof(int64_t));
250        printf("%li", *((int64_t *) value));
251    }
252    else if(strcasecmp(vartype, "int_least64_t") == 0)
253    {
254        assert(size == sizeof(int_least64_t));
255        printf("%"PRIdLEAST64, *((int_least64_t *) value));
256    }
257    else if(strcasecmp(vartype, "int_fast64_t") == 0)
258    {
259        assert(size == sizeof(int_fast64_t));
260        printf("%"PRIdFAST64, *((int_fast64_t *) value));
261    }
262    else if(strcasecmp(vartype, "uint64_t") == 0)
263    {
264        assert(size == sizeof(uint64_t));
265        printf("%lu", *((uint64_t *) value));
266    }
267    else if(strcasecmp(vartype, "uint_least64_t") == 0)
268    {
269        assert(size == sizeof(uint_least64_t));
270        printf("%"PRIuLEAST64, *((uint_least64_t *) value));
271    }
272    else if(strcasecmp(vartype, "uint_fast64_t") == 0)
273    {
274        assert(size == sizeof(uint_fast64_t));
275        printf("%"PRIuFAST64, *((uint_fast64_t *) value));
276    }
277    // Fall back to char 
278    else
279    {
280        for(int i=0; i < size; i++)
281        {
282            if ((i>0) && (i < size)) printf(", ");
283            printf("%hhu", *((char *) value));
284            value = (void *) ((uint64_t) value + sizeof(char));
285        }
286    }
287
288}
289
290void c2mpt_fix_vartype(char* fix_vartype, char* vartype)
291{
292    if((index(vartype, '*') != NULL)||
293    (strcasecmp(vartype, "char") == 0)||
294    (strcasecmp(vartype, "signed char") == 0)||
295    (strcasecmp(vartype, "unsigned char") == 0)||
296    (strcasecmp(vartype, "short") == 0)||
297    (strcasecmp(vartype, "short int") == 0)||
298    (strcasecmp(vartype, "signed short") == 0)||
299    (strcasecmp(vartype, "signed short int") == 0)||
300    (strcasecmp(vartype, "unsigned short") == 0)||
301    (strcasecmp(vartype, "unsigned short int") == 0)||
302    (strcasecmp(vartype, "int") == 0)||
303    (strcasecmp(vartype, "signed") == 0)||
304    (strcasecmp(vartype, "signed int") == 0)||
305    (strcasecmp(vartype, "unsigned") == 0)||
306    (strcasecmp(vartype, "unsigned int") == 0)||
307    (strcasecmp(vartype, "long") == 0)||
308    (strcasecmp(vartype, "long int") == 0)||
309    (strcasecmp(vartype, "signed long") == 0)||
310    (strcasecmp(vartype, "signed long int") == 0)||
311    (strcasecmp(vartype, "unsigned long") == 0)||
312    (strcasecmp(vartype, "unsigned long int") == 0)||
313    (strcasecmp(vartype, "long long") == 0)||
314    (strcasecmp(vartype, "long long int") == 0)||
315    (strcasecmp(vartype, "signed long long") == 0)||
316    (strcasecmp(vartype, "signed long long int") == 0)||
317    (strcasecmp(vartype, "float") == 0)||
318    (strcasecmp(vartype, "double") == 0)||
319    (strcasecmp(vartype, "long double") == 0)||
320    (strcasecmp(vartype, "int8_t") == 0)||
321    (strcasecmp(vartype, "int_least8_t") == 0)||
322    (strcasecmp(vartype, "int_fast8_t") == 0)||
323    (strcasecmp(vartype, "uint8_t") == 0)||
324    (strcasecmp(vartype, "uint_least8_t") == 0)||
325    (strcasecmp(vartype, "uint_fast8_t") == 0)||
326    (strcasecmp(vartype, "int16_t") == 0)||
327    (strcasecmp(vartype, "int_least16_t") == 0)||
328    (strcasecmp(vartype, "int_fast16_t") == 0)||
329    (strcasecmp(vartype, "uint16_t") == 0)||
330    (strcasecmp(vartype, "uint_least16_t") == 0)||
331    (strcasecmp(vartype, "uint_fast16_t") == 0)||
332    (strcasecmp(vartype, "int32_t") == 0)||
333    (strcasecmp(vartype, "int_least32_t") == 0)||
334    (strcasecmp(vartype, "int_fast32_t") == 0)||
335    (strcasecmp(vartype, "uint32_t") == 0)||
336    (strcasecmp(vartype, "uint_least32_t") == 0)||
337    (strcasecmp(vartype, "uint_fast32_t") == 0)||
338    (strcasecmp(vartype, "int64_t") == 0)||
339    (strcasecmp(vartype, "int_least64_t") == 0)||
340    (strcasecmp(vartype, "int_fast64_t") == 0)||
341    (strcasecmp(vartype, "uint64_t") == 0)||
342    (strcasecmp(vartype, "uint_least64_t") == 0)||
343    (strcasecmp(vartype, "uint_fast64_t") == 0))
344    {
345        strcpy(fix_vartype, vartype);
346    }
347    else
348    {
349        strcpy(fix_vartype, "uint8_t");
350    }
351
352}
353
354
355void c2mpt_dump_var(c2mpt_var var)
356{
357    uint_fast64_t i = 0;
358    uint_fast64_t multiplier = 1;
359
360    void * cval;
361    char fix_vartype[50];        
362
363    c2mpt_fix_vartype(fix_vartype, var.vartype);
364
365    if(strcasecmp(fix_vartype, var.vartype) != 0)
366    {
367        printf("WARNING: Variable '%s' is not a base type ('%s'). You might"
368                " hit endianness issues if the host and target platforms"
369                " have different endianness. Double check your initialization"
370                " data in the generated MPT file\n",
371                var.varname, var.vartype);
372        multiplier = var.elems_size;
373
374    }
375
376
377    #if __64BIT__ ||  __x86_64__ || __ppc64__ || __aarch64__ || __powerpc64__ || __s390x__
378        printf("%s = [ \"%s\", %"PRIu64", 0x%"PRIx64", %"PRIu64", ", 
379                var.varname, fix_vartype, var.nelems * multiplier,
380                (uint64_t) var.address - (uint64_t) MPT_BASE_ADDRESS, 
381                var.alignment);
382    #else
383	printf("%s = [ \"%s\", %"PRIu64", 0x%"PRIx64", %"PRIu64", ", 
384                var.varname, fix_vartype, var.nelems * multiplier,
385                (uint64_t) var.address - (uint64_t) MPT_BASE_ADDRESS,
386                var.alignment);
387    #endif
388
389    if (var.nelems > 1)
390    {
391        printf("[ ");
392    }
393
394    cval = (void *) var.address;
395    for(i=0; i < var.nelems; i++) 
396    {
397        if ((i>0) && (i < var.nelems)) printf(", ");
398        c2mpt_print_value(cval, var.elems_size, var.vartype);
399        cval = (void *) ((uint_fast64_t) cval + var.elems_size);
400    }
401
402    if (var.nelems > 1)
403    {
404    printf(" ]");
405    }
406
407    printf(" ]\n");
408
409}
410
411/****************************************************************************/
412// Main c2mpt function
413/****************************************************************************/
414
415int main(int argc, char** argv)
416{
417    c2mpt_init_global_vars();
418    c2mpt_dump_data();
419    c2mpt_function();
420    exit(0);
421}