openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

diag_sand_prt.h (53332B)


      1 
      2 /**
      3  * \file diag_sand_prt.h
      4  *
      5  * Set of macros and routines to print beautified tabular output. Main purpose to provide
      6  * standard output format for all tabular data in bcm shell
      7  */
      8 /*
      9  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
     10  * 
     11  * Copyright 2007-2020 Broadcom Inc. All rights reserved.
     12  */
     13 
     14 #ifndef DIAG_SAND_PRT_H
     15 #define DIAG_SAND_PRT_H
     16 
     17 #include <shared/utilex/utilex_rhlist.h>
     18 #include <shared/utilex/utilex_str.h>
     19 #include <shared/shrextend/shrextend_debug.h>
     20 #include <appl/diag/sand/diag_sand_utils.h>
     21 #include <appl/diag/sand/diag_sand_framework.h>
     22 
     23 #define PRT_COLUMN_WIDTH     (RHNAME_MAX_SIZE + 1)
     24 #define PRT_COLUMN_WIDTH_BIG (16 * RHNAME_MAX_SIZE + 1)
     25 #define PRT_TITLE_WIDTH      (2*RHSTRING_MAX_SIZE + 1)
     26 #define PRT_COLUMN_MAX_NUM  256
     27 #define PRT_TITLE_ID       PRT_COLUMN_MAX_NUM
     28 #define PRT_MAX_SHIFT_NUM   5
     29 
     30 typedef struct
     31 {
     32     uint32 width;
     33     char format[RHKEYWORD_MAX_SIZE];
     34     char *next_ptr;
     35     /**
     36      * sample_str - first non empty string in column, if all cells in the column will be either identical or empty
     37      *              column will be shown in info instead of actual column when option columns="nosame" was choosen
     38      */
     39     char *sample_str;
     40 } prt_format_t;
     41 
     42 /**
     43  * In order to have proper XML output, each column should be assigned XML role
     44  */
     45 typedef enum
     46 {
     47     /**
     48      * No XML output assign, column will be skipped
     49      */
     50     PRT_XML_NONE,
     51     /**
     52      * Column will be child, parent node should be figured out either through calculation or explicit input
     53      */
     54     PRT_XML_CHILD,
     55     /**
     56      * Column will be attribute, node which attribute it will be should be either calculated or provided explicitly
     57      */
     58     PRT_XML_ATTRIBUTE
     59 } PRT_XML_TYPE;
     60 
     61 /**
     62  * Flex Type - allows PRT to split either cells or headers according to different criteria into multiple rows,
     63  */
     64 typedef enum
     65 {
     66     /*
     67      * No flexibility
     68      */
     69     PRT_FLEX_NONE,
     70     /*
     71      * Split ASCII string using space, tab, point, comma or underscore (' ', '.', ',', '_', '\t')
     72      *  '\n' wil always move to the next line
     73      */
     74     PRT_FLEX_ASCII,
     75     /*
     76      * Split ASCII string using space, tab, point, comma or underscore (' ', '.', ',', '_', '\t')
     77      *  '\n' will always move to the next line
     78      *  Difference from previous is that no shrink is performed on the string
     79      */
     80     PRT_FLEX_ASCII_ORIG,
     81     /*
     82      * Split the string directly into portions of RHNAME_MAX_SIZE characters
     83      */
     84     PRT_FLEX_BINARY
     85 } PRT_FLEX_TYPE;
     86 
     87 #define         PRT_COLUMN_FLAG_SHOW         0x01
     88 #define         PRT_COLUMN_FLAG_FILTER       0x02
     89 
     90 typedef struct
     91 {
     92     /**
     93      * Column name - used in table header or as XML node name
     94      * Established only by COLUMN_ADD
     95      */
     96     char name[PRT_COLUMN_WIDTH];
     97     /**
     98      * Misc flags - Does not influence XML output
     99      * PRT_COLUMN_FLAG_SHOW     - if this flag is TRUE show column in screen table
    100      * PRT_COLUMN_FLAG_FILTER   - If this flag is TRUE use cell from this column in content filtering
    101      */
    102     int flags;
    103     /**
    104      * Flag marking whether string should be split as binary, ASCII or none
    105      * Established only by COLUMN_ADD
    106      */
    107     PRT_FLEX_TYPE flex_type;
    108     /**
    109      * Maximum size for strings in this column
    110      * Established only by COLUMN_ADD
    111      */
    112     int max_width;
    113     /**
    114      * Cell offset in the row
    115      * Established only by COLUMN_ADD
    116      */
    117     int cell_offset;
    118     void *node[PRT_MAX_SHIFT_NUM];
    119     int cur_shift_id;
    120     PRT_XML_TYPE type;
    121     char *parent_name;
    122     int parent_id;
    123     int depth;
    124     int align;
    125 } prt_column_t;
    126 
    127 typedef struct
    128 {
    129     /*
    130      * Entry used to be queued on info_list
    131      */
    132     rhentry_t entry;
    133     /*
    134      * Allow info length be the same as title one
    135      */
    136     char content[PRT_TITLE_WIDTH];
    137 } prt_info_t;
    138 
    139 typedef struct
    140 {
    141     /*
    142      * Assigned once when we now the sum of all column widths by the first row added
    143      */
    144     rhlist_t *list;
    145     /*
    146      * Unit id
    147      */
    148     int unit;
    149     /*
    150      * Modified by PRT_COLUMN_ADD, first PRT_ROW_ADD blocks the option for column changes
    151      */
    152     int col_num;
    153     /*
    154      * Sum of the all column max widths, modified only by PRT_COLUMN_ADD
    155      */
    156     int row_width;
    157     /**
    158      * Desirable display width, set around in PRT_TITLE_SET or left undefined which prompts 64 character per column
    159      */
    160     int display_width;
    161     /*
    162      * Separate place for title to allow bigger string
    163      */
    164     char title[PRT_TITLE_WIDTH];
    165     /*
    166      * Contain per column info - keep + 1 - it is for title node
    167      */
    168     prt_column_t *columns[PRT_COLUMN_MAX_NUM + 1];
    169     /*
    170      * Dynamic parameter - used to keep current entry
    171      */
    172     void *row_cur;
    173     /*
    174      * Dynamic parameter - current column in the row
    175      */
    176     int col_cur;
    177     /*
    178      * Per table information list
    179      */
    180     rhlist_t *info_list;
    181 } prt_control_t;
    182 
    183 /**
    184  * \brief Get the width of the terminal to best output fit
    185  * \par DIRECT OUTPUT
    186  * \retval - terminal width
    187  */
    188 int diag_sand_prt_width(
    189     void);
    190 
    191 /**
    192  * \brief Print number of identical characters
    193  * \par DIRECT INPUT
    194  *  \param num [in] number of characters to print
    195  *  \param ch [in] character to print
    196  * \par DIRECT OUTPUT
    197  * \retval - terminal width
    198  */
    199 void diag_sand_prt_char(
    200     int num,
    201     char ch);
    202 
    203 /**
    204  * \brief Actual output of prepared data either to display or XML file
    205  * \param prt_ctr [in/out] pointer to the control list of table print
    206  * \param sand_control [in] pointer to control block of shell command. NULL means that command was invocated by framework
    207  * \param prt_filename [in] explicit XML filename to write the table to
    208  * \remark
    209  *      OUTPUT: printing or formatted output to the standard output/XML File
    210  */
    211 shr_error_e diag_sand_prt(
    212     prt_control_t * prt_ctr,
    213     sh_sand_control_t * sand_control,
    214     char *prt_filename);
    215 
    216 /**
    217  * \brief Actual output of prepared data to display (multiple tables)
    218  * \param prt_ctr [in/out] pointer to the control list of tables to print
    219  * \param sand_control [in] pointer to control block of shell command. NULL means that command was invocated by framework
    220  * \param table_count [in] Table count.
    221  * \remark
    222  *      OUTPUT: printing or formatted output to the standard output.
    223  */
    224 shr_error_e diag_sand_prt_multiple(
    225     prt_control_t ** prt_ctr,
    226     sh_sand_control_t * sand_control,
    227     uint32 table_count);
    228 
    229 /**
    230  * \brief Add new column to the table
    231  * \param prt_ctr [in/out]      - pointer to the control list of table print
    232  * \param flag [in]             - mark different properties of column
    233  * \param width [in]            - column width
    234  * \param prt_column_p [out]    - pointer to column pointer
    235  * \remark
    236  *    Should not be used outside the diag_sand_prt MACROs
    237  */
    238 shr_error_e diag_sand_prt_column_add(
    239     prt_control_t * prt_ctr,
    240     int flag,
    241     int width,
    242     prt_column_t ** prt_column_p);
    243 
    244 /**
    245  * \brief Sanitize XML gold result file - like remove timestamp and may be other things to consider
    246  * \param unit     [in]      - device id
    247  * \param flags     [in]     - flags used for gold result path.
    248  * \param command  [in]      - command string for the file to be sanitized
    249  * \param filename [in]      - filename build for this command
    250  * \remark
    251  *    should be kept as internal routine
    252  */
    253 shr_error_e diag_sand_prt_gold_sanitize(
    254     int unit,
    255     int flags,
    256     char *command,
    257     char *filename);
    258 
    259 /*
    260  * Modes for list entries
    261  */
    262 typedef enum
    263 {
    264     /**
    265      * No separation line
    266      */
    267     PRT_ROW_SEP_NONE,
    268     /**
    269      * Underscore(__________) line after the row
    270      */
    271     PRT_ROW_SEP_UNDERSCORE,
    272     /**
    273      * Underscore(__________) line before the row
    274      */
    275     PRT_ROW_SEP_UNDERSCORE_BEFORE,
    276     /**
    277      * Equal(==========) line after  the row
    278      */
    279     PRT_ROW_SEP_EQUAL,
    280     /**
    281      * Equal(==========) line before  the row
    282      */
    283     PRT_ROW_SEP_EQUAL_BEFORE,
    284 
    285 } PRT_ROW_SEP_MODE;
    286 
    287 /*
    288  * Internal Facilities for pretty print not to be used outside this include file
    289  * {
    290  */
    291 #define _PRT_FORMAT(mc_ptr, mc_length, mc_format,...) {                                                                \
    292                                        sal_snprintf(mc_ptr, mc_length, mc_format "%s", __VA_ARGS__);                   \
    293                                      }
    294 #define PRT_FORMAT(mc_ptr, mc_length,...) {                                                                            \
    295                                        _PRT_FORMAT(mc_ptr, mc_length, __VA_ARGS__, "");                                \
    296                                      }
    297 
    298 #define PRT_COLUMN_ITERATOR(k_mc, prt_column_mc, prt_ctr_mc)                                                           \
    299         for (k_mc = 0, prt_column_mc = prt_ctr->columns[0]; k_mc < prt_ctr_mc->col_num;                                \
    300                                                            k_mc++, prt_column_mc = prt_ctr->columns[k_mc])             \
    301         if(prt_column_mc->flags & PRT_COLUMN_FLAG_SHOW)
    302 
    303 #define PRT_FILTER_COLUMN_ITERATOR(k_mc, prt_column_mc, prt_ctr_mc)                                                    \
    304         for (k_mc = 0, prt_column_mc = prt_ctr->columns[0]; k_mc < prt_ctr_mc->col_num;                                \
    305                                                            k_mc++, prt_column_mc = prt_ctr->columns[k_mc])             \
    306         if(prt_column_mc->flags & PRT_COLUMN_FLAG_FILTER)
    307 
    308 #define PRT_HIDDEN_COLUMN_ITERATOR(k_mc, prt_column_mc, prt_ctr_mc)                                                    \
    309         for (k_mc = 0, prt_column_mc = prt_ctr->columns[0]; k_mc < prt_ctr_mc->col_num;                                \
    310                                                            k_mc++, prt_column_mc = prt_ctr->columns[k_mc])             \
    311         if(!(prt_column_mc->flags & PRT_COLUMN_FLAG_SHOW))
    312 
    313 #define PRT_ALL_COLUMN_ITERATOR(k_mc, prt_column_mc, prt_ctr_mc)                                                       \
    314         for (k_mc = 0, prt_column_mc = prt_ctr->columns[0]; k_mc < prt_ctr_mc->col_num;                                \
    315                                                            k_mc++, prt_column_mc = prt_ctr->columns[k_mc])
    316 
    317 /**
    318  * \brief Free control structure allocated by _SET_TITLE
    319  * \param [in] prt_ctr_mc - pointer to the control structure
    320  * \remark
    321  *     Should be always used at the end(usually after exit: label) of routine using pretty printing to catch all errors
    322  */
    323 #define _PRT_FREE(prt_ctr_mc)                                                                                          \
    324     if(prt_ctr_mc != NULL)                                                                                             \
    325     {                                                                                                                  \
    326         int i_col;                                                                                                     \
    327         for(i_col = 0; i_col < prt_ctr_mc->col_num; i_col++)                                                           \
    328         {                                                                                                              \
    329             if(prt_ctr_mc->columns[i_col] != NULL)                                                                     \
    330                 sal_free(prt_ctr_mc->columns[i_col]);                                                                  \
    331         }                                                                                                              \
    332         if(prt_ctr_mc->columns[PRT_TITLE_ID] != NULL)                                                                  \
    333             sal_free(prt_ctr_mc->columns[PRT_TITLE_ID]);                                                               \
    334         if(prt_ctr_mc->list != NULL)                                                                                   \
    335             utilex_rhlist_free_all(prt_ctr_mc->list);                                                                  \
    336         if(prt_ctr_mc->info_list != NULL)                                                                              \
    337             utilex_rhlist_free_all(prt_ctr_mc->info_list);                                                             \
    338         sal_free(prt_ctr_mc);                                                                                          \
    339         prt_ctr_mc = NULL;                                                                                             \
    340     }
    341 
    342 /**
    343  * \brief Actual printing of prepared data to be used only in the context of shell framework
    344  * \param prt_ctr_mc [in] - pointer to the control structure
    345  * \remark
    346  *    Requires presence of sand_control, which is implicitly provided by the shell command invocation parameters, and
    347  *    should be transfered to underlying routines in the case of PRT usage down stack
    348  *    Frees the list
    349  */
    350 #define _PRT_COMMITX(prt_ctr_mc) {                                                                                     \
    351         SHR_CLI_EXIT_IF_ERR(diag_sand_prt(prt_ctr_mc, sand_control, NULL), "");                                        \
    352         _PRT_FREE(prt_ctr_mc);                                                                                         \
    353     }
    354 
    355 /**
    356  * \brief Actual printing of prepared data, like PRT_COMMITX, but with on option to use explicit XML output file name
    357  * \par DIRECT INPUT
    358  * \param [in] prt_ctr_mc - pointer to the control structure
    359  * \param [in] filename_str - XML file to be used for data export, if NULL the one from sand_control may be used
    360  * \par INDIRECT INPUT: prt_ctr_mc      - control structure that provides all the info on the table
    361  *                      sand_control - control structure that provides all command related info
    362  * \par INDIRECT OUTPUT: printing or formatted output to the standard output
    363  * \remark automatically frees the list
    364  */
    365 #define _PRT_COMMITF(prt_ctr_mc, filename_str) {                                                                       \
    366         SHR_CLI_EXIT_IF_ERR(diag_sand_prt(prt_ctr_mc, sand_control, filename_str), "");                                \
    367         _PRT_FREE(prt_ctr_mc);                                                                                         \
    368     }
    369 
    370 /**
    371  * \brief Same as PRT_COMMITX, the difference being to be used when no shell framework sand_control is now available
    372  * \param [in] prt_ctr_mc - pointer to the control structure
    373  * \par INDIRECT OUTPUT: printing or formatted output to the standard output
    374  * \remark automatically frees the list
    375  */
    376 #define _PRT_COMMIT(prt_ctr_mc)                                                                                        \
    377 {                                                                                                                      \
    378     SHR_CLI_EXIT_IF_ERR(diag_sand_prt(prt_ctr_mc, NULL, NULL), "");                                                    \
    379     _PRT_FREE(prt_ctr_mc);                                                                                             \
    380 }
    381 
    382 /**
    383  * \brief Same as PRT_COMMITX, the difference being to be is that it is printing several tables as one.
    384  * \param prt_ctr_mc [in] - pointer to the control structure
    385  * \param mc_num [in] - number of tables to print.
    386  * \remark
    387  *    Requires presence of sand_control, which is implicitly provided by the shell command invocation parameters, and
    388  *    should be transfered to underlying routines in the case of PRT usage down stack
    389  *    Does NOT frees the list, as we may want to print part of the set separately
    390  */
    391 #define _PRT_COMMITX_COMBINE(prt_ctr_mc, mc_num)                                                                      \
    392 {                                                                                                                      \
    393         SHR_CLI_EXIT_IF_ERR(diag_sand_prt_multiple(prt_ctr_mc, sand_control, mc_num), "");                               \
    394 }
    395 
    396 /**
    397  * \brief Verifies validity if row/column position
    398  * \param [in] prt_ctr_mc - pointer to the control structure
    399  */
    400 #define _PRT_CELL_VERIFY(prt_ctr_mc) \
    401             if(prt_ctr_mc->row_cur == NULL)                                                                            \
    402             {                                                                                                          \
    403                 SHR_CLI_EXIT(_SHR_E_INTERNAL, "First row for the table was not allocated\n");                          \
    404             }                                                                                                          \
    405             if(prt_ctr_mc->col_cur >= prt_ctr_mc->col_num)                                                             \
    406             {                                                                                                          \
    407                 SHR_CLI_EXIT(_SHR_E_INTERNAL, "Cell setting column:%d number of columns:%d\n",                         \
    408                                                                  prt_ctr_mc->col_cur + 1, prt_ctr_mc->col_num);        \
    409             }                                                                                                          \
    410             if(prt_ctr_mc->columns[prt_ctr_mc->col_cur] == NULL)                                                       \
    411             {                                                                                                          \
    412                 SHR_CLI_EXIT(_SHR_E_INTERNAL, "Column:%d was not allocated\n", prt_ctr_mc->col_cur);                   \
    413             }
    414 
    415 /**
    416  * \brief Fill cell with formatted data
    417  * \param prt_ctr_mc [in] - pointer to the control structure
    418  * \par INDIRECT OUTPUT prt_ctr_mc->col_cur is updated, so to reflect that cell was filled
    419  */
    420 #define _PRT_CELL_SET(prt_ctr_mc, ...) \
    421 {                                                                                                                     \
    422     char *prt_row_offset;                                                                                             \
    423     prt_column_t *prt_column_mc;                                                                                      \
    424     _PRT_CELL_VERIFY(prt_ctr_mc)                                                                                      \
    425     prt_column_mc = prt_ctr_mc->columns[prt_ctr_mc->col_cur];                                                         \
    426     prt_row_offset = (char *)prt_ctr_mc->row_cur + sizeof(rhentry_t) + prt_column_mc->cell_offset;                    \
    427     PRT_FORMAT(prt_row_offset, prt_column_mc->max_width, __VA_ARGS__);                                                \
    428     if (prt_column_mc->flex_type == PRT_FLEX_ASCII)                                                                   \
    429     {                                                                                                                 \
    430         utilex_str_shrink(prt_row_offset);                                                                            \
    431     }                                                                                                                 \
    432     prt_row_offset[prt_column_mc->max_width - 1] = 0;                                                                 \
    433     prt_ctr_mc->col_cur++;                                                                                            \
    434 }
    435 
    436 /**
    437  * \brief Fill cell with formatted data
    438  * \par DIRECT INPUT variadic variables
    439  * \param [in] prt_ctr_mc - pointer to the control structure
    440  * \param [in] prt_n - number of shift in the cell, each shift is 2 spaces
    441  * \par INDIRECT OUTPUT prt_ctr_mc->col_cur is updated, so to reflect that cell was filled
    442  */
    443 #define _PRT_CELL_SET_SHIFT(prt_ctr_mc, prt_n, ...) \
    444 {                                                                                                                      \
    445     char *prt_row_offset;                                                                                              \
    446     prt_column_t *prt_column_mc;                                                                                       \
    447     _PRT_CELL_VERIFY(prt_ctr_mc)                                                                                       \
    448     prt_column_mc = prt_ctr_mc->columns[prt_ctr_mc->col_cur];                                                          \
    449     prt_row_offset = (char *)prt_ctr_mc->row_cur + sizeof(rhentry_t) + prt_column_mc->cell_offset;                     \
    450     {                                                                                                                  \
    451         int shift_num  = prt_n;                                                                                        \
    452         while(shift_num--)                                                                                             \
    453         {                                                                                                              \
    454             PRT_FORMAT(prt_row_offset + strlen(prt_row_offset), prt_column_mc->max_width, "  ");                       \
    455         }                                                                                                              \
    456     }                                                                                                                  \
    457     PRT_FORMAT(prt_row_offset + strlen(prt_row_offset), prt_column_mc->max_width, __VA_ARGS__);                        \
    458     prt_row_offset[prt_column_mc->max_width - 1] = 0;                                                                  \
    459     prt_ctr_mc->col_cur++;                                                                                             \
    460 }
    461 
    462 /**
    463  * \brief When filling table allows to skip cell
    464  * \par DIRECT INPUT
    465  * \param [in] prt_ctr_mc - pointer to the control structure
    466  * \param [in] mc_skip_num - number of cells to be skipped
    467  * \par INDIRECT OUTPUT prt_ctr_mc->col_cur is updated, so to reflect that cell was filled
    468  */
    469 #define _PRT_CELL_SKIP(prt_ctr_mc, mc_skip_num)                                                                        \
    470 {                                                                                                                      \
    471     _PRT_CELL_VERIFY(prt_ctr_mc)                                                                                       \
    472     prt_ctr_mc->col_cur += mc_skip_num;                                                                                \
    473 }
    474 
    475 /**
    476  * \brief Add Info Line after the title and before actual table starts
    477  * \par DIRECT INPUT variadic variables
    478  * \param [in] prt_ctr_mc - pointer to the control structure
    479  * \par INDIRECT INPUT prt_ctr_mc - Control structure containing information on table to be printed
    480  * \remark MACRO limits the size to RHNAME_MAX_SIZE
    481  */
    482 #define _PRT_INFO_ADD(prt_ctr_mc, ...) \
    483 {                                                                                                                      \
    484     rhhandle_t entry;                                                                                                  \
    485     if(prt_ctr_mc == NULL)                                                                                             \
    486     {                                                                                                                  \
    487         SHR_CLI_EXIT(_SHR_E_INTERNAL, "Title was not defined\n");                                                      \
    488     }                                                                                                                  \
    489     if(prt_ctr_mc->info_list == NULL)                                                                                  \
    490     {                                                                                                                  \
    491         if((prt_ctr_mc->info_list = utilex_rhlist_create("prt_print", sizeof(prt_info_t), 0)) == NULL)                 \
    492         {                                                                                                              \
    493             SHR_CLI_EXIT(_SHR_E_MEMORY,"info_list create %s", "failed\n");                                             \
    494         }                                                                                                              \
    495     }                                                                                                                  \
    496     if(utilex_rhlist_entry_add_tail(prt_ctr_mc->info_list, NULL, RHID_TO_BE_GENERATED, &entry) == _SHR_E_MEMORY)       \
    497     {                                                                                                                  \
    498          SHR_CLI_EXIT(_SHR_E_MEMORY,"add entry to info_list  %s", "failed\n");                                         \
    499     }                                                                                                                  \
    500     ((rhentry_t *)entry)->mode = PRT_ROW_SEP_NONE;                                                               \
    501     PRT_FORMAT(((prt_info_t *)entry)->content, PRT_TITLE_WIDTH - 1, __VA_ARGS__);                                                       \
    502 }
    503 
    504 /**
    505  * \brief Set separator for the last info - how it will be separated from previous line
    506  * \param [in] prt_ctr_mc - pointer to the control structure
    507  * \par DIRECT INPUT
    508  * \param [in] mc_mode Type of separator from previous line. See PRT_ROW_SEP_MODE
    509  */
    510 #define _PRT_INFO_SET_MODE(prt_ctr_mc, mc_mode)                                                                        \
    511 {                                                                                                                      \
    512     rhentry_t *entry;                                                                                                  \
    513     if((entry = utilex_rhlist_entry_get_last(prt_ctr_mc->info_list)) == NULL)                                          \
    514     {                                                                                                                  \
    515         SHR_CLI_EXIT(_SHR_E_MEMORY,"Setting info mode while no info added\n");                                         \
    516     }                                                                                                                  \
    517     else                                                                                                               \
    518     {                                                                                                                  \
    519         entry->mode = mc_mode;                                                                                         \
    520     }                                                                                                                  \
    521 }
    522 
    523 /**
    524  * \brief Low Level Add column routine
    525  * \par DIRECT INPUT variadic variables
    526  * \param [in] prt_ctr_mc - pointer to the control structure
    527  * \param [in] flag - points to the FLEX type of the column to be created, either BINARY or ASCII, see PRT_FLEX_TYPE
    528  * \param [in] width - maximum width for cell in the column
    529  * \par INDIRECT INPUT prt_ctr_mc - Control structure containing information on table to be printed
    530  * \remark MACRO verifies the number of column does not exceed MAX
    531  */
    532 #define _PRT_COLUMN_ADD(prt_ctr_mc, flag, width, ...)                                                                  \
    533 {                                                                                                                      \
    534     prt_column_t *prt_column;                                                                                          \
    535     SHR_CLI_EXIT_IF_ERR(diag_sand_prt_column_add(prt_ctr_mc, flag, width, &prt_column),"");                            \
    536     PRT_FORMAT(prt_column->name, prt_column->max_width, __VA_ARGS__);                                                  \
    537 }
    538 
    539 #define _PRT_COLUMN_ALIGN(prt_ctr_mc)                                                                                  \
    540     if((prt_ctr_mc->col_num == 0) || (prt_ctr_mc->columns[prt_ctr_mc->col_num - 1] == NULL))                           \
    541     {                                                                                                                  \
    542         SHR_CLI_EXIT(_SHR_E_MEMORY, "Align for non-allocated column\n");                                               \
    543     }                                                                                                                  \
    544     prt_ctr_mc->columns[prt_ctr_mc->col_num - 1]->align = TRUE
    545 
    546 /**
    547  * \brief Add column
    548  * \par DIRECT INPUT variadic variables
    549  * \param [in] prt_ctr_mc - pointer to the control structure
    550  * \param [in] prt_type - type of XML node to be created, may be either PRT_XML_CHILD, PRT_XML_ATTRUBUTE or PRT_XML_NONE
    551  * \param [in] prt_parent_id - id for parent XML node
    552  * \par DIRECT OUTPUT
    553  * \param [out] prt_my_id_ptr - pointer for id of this column
    554  * \par INDIRECT INPUT prt_ctr_mc - Control structure containing information on table to be printed
    555  * \remark MACRO verifies the number of column does not exceed MAX
    556  */
    557 #define _PRT_COLUMN_ADDX(prt_ctr_mc, prt_type, prt_parent_id, prt_my_id_ptr, ...)                                      \
    558 {                                                                                                                      \
    559     _PRT_COLUMN_ADD(prt_ctr_mc, PRT_FLEX_NONE, PRT_COLUMN_WIDTH, __VA_ARGS__)                                          \
    560     {                                                                                                                  \
    561         int *loc_my_id_ptr = prt_my_id_ptr;                                                                            \
    562         prt_ctr_mc->columns[prt_ctr_mc->col_num - 1]->type      = prt_type;                                            \
    563         prt_ctr_mc->columns[prt_ctr_mc->col_num - 1]->parent_id = prt_parent_id;                                       \
    564         if(loc_my_id_ptr != NULL)                                                                                      \
    565             *loc_my_id_ptr = prt_ctr_mc->col_num - 1;                                                                  \
    566     }                                                                                                                  \
    567 }
    568 
    569 /**
    570  * \brief Add column
    571  * \par DIRECT INPUT variadic variables
    572  * \param [in] prt_ctr_mc - pointer to the control structure
    573  * \param [in] flag - points to the FLEX type of the column to be created, either BINARY or ASCII, see PRT_FLEX_TYPE
    574  * \param [in] prt_type - type of XML node to be created, may be either PRT_XML_CHILD, PRT_XML_ATTRUBUTE or PRT_XML_NONE
    575  * \param [in] prt_parent_id - id for parent XML node
    576  * \par DIRECT OUTPUT
    577  * \param [out] prt_my_id_ptr - pointer for id of this column
    578  * \par INDIRECT INPUT prt_ctr_mc - Control structure containing information on table to be printed
    579  * \remark MACRO verifies the number of column does not exceed MAX
    580  */
    581 #define _PRT_COLUMN_ADDX_FLEX(prt_ctr_mc, flag, prt_type, prt_parent_id, prt_my_id_ptr, ...)                           \
    582 {                                                                                                                      \
    583     _PRT_COLUMN_ADD(prt_ctr_mc, flag, PRT_COLUMN_WIDTH_BIG, __VA_ARGS__)                                               \
    584     {                                                                                                                  \
    585         int *loc_my_id_ptr = prt_my_id_ptr;                                                                            \
    586         prt_ctr_mc->columns[prt_ctr_mc->col_num - 1]->type      = prt_type;                                            \
    587         prt_ctr_mc->columns[prt_ctr_mc->col_num - 1]->parent_id = prt_parent_id;                                       \
    588         if(loc_my_id_ptr != NULL)                                                                                      \
    589             *loc_my_id_ptr = prt_ctr_mc->col_num - 1;                                                                  \
    590     }                                                                                                                  \
    591 }
    592 
    593 /**
    594  * \brief Set Title String for tabular output, it may appear as most upper string on display and top XML node
    595  * \par DIRECT INPUT variadic variables
    596  * \param [in] prt_ctr_mc - pointer to the control structure
    597  * \par INDIRECT OUTPUT
    598  *         prt_ctr_mc->columns[PRT_TITLE_ID] - title prt column is updated
    599  */
    600 #define _PRT_TITLE_SET(prt_ctr_mc, ...)                                                                                \
    601 {                                                                                                                      \
    602     if(prt_ctr_mc != NULL)                                                                                             \
    603     {                                                                                                                  \
    604         SHR_CLI_EXIT(_SHR_E_INTERNAL, "Title may be defined only once\n");                                             \
    605     }                                                                                                                  \
    606     if((prt_ctr_mc = sal_alloc(sizeof(prt_control_t), "prt_control")) == NULL)                                         \
    607     {                                                                                                                  \
    608         SHR_CLI_EXIT(_SHR_E_MEMORY, "No memory for PRT table\n");                                                      \
    609     }                                                                                                                  \
    610     sal_memset(prt_ctr_mc, 0, sizeof(prt_control_t));                                                                  \
    611     if((prt_ctr_mc->columns[PRT_TITLE_ID] = sal_alloc(sizeof(*(prt_ctr_mc->columns[PRT_TITLE_ID])), "prt_title")) == NULL)  \
    612     {                                                                                                                  \
    613         SHR_CLI_EXIT(_SHR_E_MEMORY, "No memory for PRT title\n");                                                      \
    614     }                                                                                                                  \
    615     sal_memset(prt_ctr_mc->columns[PRT_TITLE_ID], 0, sizeof(*(prt_ctr_mc->columns[PRT_TITLE_ID])) );                    \
    616     prt_ctr_mc->unit = unit;                                                                                           \
    617     prt_ctr_mc->columns[PRT_TITLE_ID]->depth = 1;                                                                      \
    618     PRT_FORMAT(prt_ctr_mc->title, PRT_TITLE_WIDTH, __VA_ARGS__);                                                       \
    619     PRT_FORMAT(prt_ctr_mc->columns[PRT_TITLE_ID]->name, PRT_COLUMN_WIDTH, __VA_ARGS__);                                \
    620 }
    621 
    622 /**
    623  * \brief Check if the print title is set.
    624  * \param [in] prt_ctr_mc - pointer to the control structure
    625  * \par DIRECT OUTPUT
    626  * \retval - return 1 if the title is already set, 0 if it is not.
    627  */
    628 #define _PRT_TITLE_IS_SET(prt_ctr_mc) ((prt_ctr_mc != NULL) ? 1 : 0)
    629 
    630 /**
    631  * \brief Return the total number of columns in the table Used to derive number of columns in the table
    632  * \param [in] prt_ctr_mc - pointer to the control structure
    633  * \par DIRECT OUTPUT
    634  * \retval - number of columns
    635  */
    636 #define _PRT_COLUMN_NUM(prt_ctr_mc)               prt_ctr_mc->col_num
    637 
    638 /**
    639  * \brief Add new row in the table
    640  * \par DIRECT INPUT
    641  * \param [in] prt_ctr_mc - pointer to the control structure
    642  * \param [in] mc_mode Points to the type of separator from previous line. See PRT_ROW_SEP_MODE
    643  * \par INDIRECT INPUT prt_list - pointer to the list of rows, that this one will be added to
    644  *                     prt_row_offset - current place in the row to be written (cell pointer)
    645  *                     prt_row_start - pointer to the beginning of row
    646  * \par INDIRECT OUTPUT prt_list - new row will be added to this list
    647  *                      prt_row_start - pointer to the beginning of new row
    648  *                      prt_row_offset - set to the beginning of new row skipping control info
    649  * \remark First row filled followed by ROW_COLUMN_SET is considered of being header one
    650  */
    651 #define _PRT_ROW_ADD(prt_ctr_mc, mc_mode) \
    652 {                                                                                                                      \
    653     prt_ctr_mc->col_cur = 0;                                                                                           \
    654     if(prt_ctr_mc->list == NULL)                                                                                       \
    655     {                                                                                                                  \
    656         if((prt_ctr_mc->list = utilex_rhlist_create("prt_print", sizeof(rhentry_t) + prt_ctr_mc->row_width, 0)) == NULL)     \
    657         {                                                                                                              \
    658             SHR_CLI_EXIT(_SHR_E_MEMORY,"prt_list create %s", "failed\n");                                              \
    659         }                                                                                                              \
    660     }                                                                                                                  \
    661     if(utilex_rhlist_entry_add_tail(prt_ctr_mc->list, NULL, RHID_TO_BE_GENERATED, &(prt_ctr_mc->row_cur)) == _SHR_E_MEMORY)    \
    662     {                                                                                                                  \
    663          SHR_CLI_EXIT(_SHR_E_MEMORY,"add entry to prt_list  %s", "failed\n");                                          \
    664     }                                                                                                                  \
    665     ((rhentry_t *)(prt_ctr_mc->row_cur))->mode = mc_mode;                                                              \
    666 }
    667 
    668 /**
    669  * \brief Delete Last Row in the table
    670  * \par DIRECT INPUT
    671  * \param [in] prt_ctr_mc - pointer to the control structure
    672  * \remark Last Roe will be deleted, used when in process of PRT we decide to skip certain row
    673  */
    674 #define _PRT_ROW_DELETE(prt_ctr_mc) \
    675 {                                                                                                                      \
    676     prt_ctr_mc->col_cur = 0;                                                                                           \
    677     if(prt_ctr_mc->list != NULL)                                                                                       \
    678     {                                                                                                                  \
    679         rhhandle_t *rhentry = utilex_rhlist_entry_get_last(prt_ctr_mc->list);                                          \
    680         utilex_rhlist_entry_del_free(prt_ctr_mc->list, rhentry);                                                       \
    681     }                                                                                                                  \
    682 }
    683 
    684 /**
    685  * \brief Return number of rows in the table
    686  * \param [in] prt_ctr_mc - pointer to the control structure
    687  */
    688 #define _PRT_ROW_NUM(prt_ctr_mc)     ((prt_ctr_mc->list != NULL) ? RHLNUM(prt_ctr_mc->list) : 0)
    689 
    690 /**
    691  * \brief Set mode for the last row
    692  * \param [in] prt_ctr_mc - pointer to the control structure
    693  * \par DIRECT INPUT
    694  * \param [in] mc_mode Type of separator from previous line. See PRT_ROW_SEP_MODE
    695  */
    696 #define _PRT_ROW_SET_MODE(prt_ctr_mc, mc_mode)                                                                         \
    697 {                                                                                                                      \
    698     if(prt_ctr_mc->row_cur == NULL)                                                                                    \
    699     {   /* If there are no rows yet - add one to assign mode to */                                                     \
    700         _PRT_ROW_ADD(prt_ctr_mc, mc_mode);                                                                             \
    701     }                                                                                                                  \
    702     else                                                                                                               \
    703     {                                                                                                                  \
    704         ((rhentry_t *)(prt_ctr_mc->row_cur))->mode = mc_mode;                                                          \
    705     }                                                                                                                  \
    706 }
    707 /*
    708  * End of internal pretty printing facilities
    709  * }
    710  */
    711 
    712 /*
    713  * Below MACROs are for external usage when only 1 table is required
    714  * {
    715  */
    716 /**
    717  * \brief
    718  *    1. Declares pointer to control structure used by pretty printing
    719  *    2. Invocation should be before any code start
    720  *    3. Pointer declared here may be passed down the line in order to have an ability to add cells to the table over
    721  *       multiple routines
    722  *    4. The requirement is to invoke PRT_TITLE_SET, PRT_COMMIT and PRT_FREE only from the routine with PRT_INIT_VARS
    723  */
    724 #define PRT_INIT_VARS                prt_control_t *prt_ctr = NULL
    725 
    726 /**
    727  * \brief
    728  *    1. Should be set once per table
    729  *    2. Accepts regular printf format
    730  * \par DIRECT INPUT variadic variables
    731  */
    732 #define PRT_TITLE_SET(...)          _PRT_TITLE_SET(prt_ctr, __VA_ARGS__)
    733 #define PRT_TITLE_IS_SET            _PRT_TITLE_IS_SET(prt_ctr)
    734 /**
    735  * \brief Add Info
    736  * \par DIRECT INPUT variadic variables
    737  * \par INDIRECT INPUT prt_ctr_mc - Control structure containing information on table to be printed
    738  * \remark
    739  *    1. MACRO limits the size to RHNAME_MAX_SIZE - 1
    740  *    2. In XML output all infos will be added to special node at the beginning of the file
    741  */
    742 #define PRT_INFO_ADD(...)           _PRT_INFO_ADD(prt_ctr, __VA_ARGS__)
    743 
    744 /**
    745  * \brief Set mode for the last row
    746  * \par DIRECT INPUT
    747  * \param [in] mc_mode Type of separator from previous line. See PRT_ROW_SEP_MODE
    748  * \remark
    749  *    Used when the mode could be figured only after it is filled, e.g. when we understand the the row we printed is the
    750  *    last for certain logic
    751  */
    752 #define PRT_INFO_SET_MODE(mc_mode)       _PRT_INFO_SET_MODE(prt_ctr, mc_mode)
    753 
    754 /**
    755  * \brief Add column to the table with text provided in regular printf format
    756  * \par DIRECT INPUT variadic variables
    757  * \par INDIRECT INPUT prt_ctr_mc - Control structure containing information on table to be printed
    758  * \remark
    759  *    MACRO verifies the number of column does not exceed MAX
    760  */
    761 #define PRT_COLUMN_ADD(...) _PRT_COLUMN_ADD(prt_ctr, PRT_FLEX_NONE, PRT_COLUMN_WIDTH, __VA_ARGS__)
    762 
    763 /**
    764  * \brief
    765  *    1. Allows to have cells with size over RHNAME_MAX_SIZE, where cell content is split over multiple rows in the
    766  *       same column up to PRT_COLUMN_WIDTH_BIG - 1
    767  *    2. When column header is bigger than max cell size in the column it will be split over the multiple rows inside
    768  *       header line
    769  * \par DIRECT INPUT variadic variables
    770  * \param [in] flag - points to the FLEX type of the column to be created, either BINARY or ASCII, see PRT_FLEX_TYPE
    771  * \par INDIRECT INPUT prt_ctr_mc - Control structure containing information on table to be printed
    772  * \remark
    773  *    1. MACRO verifies the number of column does not exceed MAX
    774  *    2. Use binary for long numbers presentation
    775  *    3. Use ASCII for string output
    776  */
    777 #define PRT_COLUMN_ADD_FLEX(flag, ...)  _PRT_COLUMN_ADD(prt_ctr, flag, PRT_COLUMN_WIDTH_BIG, __VA_ARGS__)
    778 
    779 /**
    780  * \brief Add column with specific instructions on XML location
    781  * \par DIRECT INPUT variadic variables
    782  * \param [in] prt_type - type of XML node to be created, may be either PRT_XML_CHILD, PRT_XML_ATTRUBUTE or PRT_XML_NONE
    783  * \param [in] prt_parent_id - id for parent XML node
    784  * \param [out] prt_my_id_ptr - pointer for id of this column
    785  * \par INDIRECT INPUT prt_ctr_mc - Control structure containing information on table to be printed
    786  * \remark
    787  *    1. Used in the cases where automatic XML placement does not work, so you need to state explicitly which type do
    788  *       you want this column to be. See PRT_XML_TYPE for options
    789  *    2. MACRO verifies the number of column does not exceed MAX
    790  */
    791 #define PRT_COLUMN_ADDX(prt_type, prt_parent_id, prt_my_id_ptr, ...) \
    792                     _PRT_COLUMN_ADDX(prt_ctr, prt_type, prt_parent_id, prt_my_id_ptr, __VA_ARGS__)
    793 /**
    794  * \brief
    795  *    Combination of PRT_COLUMN_ADDX with flexibility option, see above
    796  * \param [in] flag - points to the FLEX type of the column to be created, either BINARY or ASCII, see PRT_FLEX_TYPE
    797  * \param [in] prt_type - type of XML node to be created, may be either PRT_XML_CHILD, PRT_XML_ATTRUBUTE or PRT_XML_NONE
    798  * \param [in] prt_parent_id - id for parent XML node
    799  * \param [out] prt_my_id_ptr - pointer for id of this column
    800  */
    801 #define PRT_COLUMN_ADDX_FLEX(flag, prt_type, prt_parent_id, prt_my_id_ptr, ...)                                       \
    802                     _PRT_COLUMN_ADDX_FLEX(prt_ctr, flag, prt_type, prt_parent_id, prt_my_id_ptr, __VA_ARGS__)
    803 
    804 /**
    805  * \brief
    806  *    Aligns current column content to the right. By default all columns are aligned to the left
    807  *    Should be called right after COLUMN_ADD
    808  */
    809 #define PRT_COLUMN_ALIGN                _PRT_COLUMN_ALIGN(prt_ctr)
    810 
    811 /**
    812  * \brief
    813  *    Returns current column number, is useful to calculate how many columns should be skipped when dealing with table,
    814  *    where number an order of columns is parameter dependent
    815  */
    816 #define PRT_COLUMN_NUM                  _PRT_COLUMN_NUM(prt_ctr)
    817 
    818 /**
    819  * \brief Set mode for the last row
    820  * \par DIRECT INPUT
    821  * \param [in] mc_mode Type of separator from previous line. See PRT_ROW_SEP_MODE
    822  * \remark
    823  *    Used when the mode could be figured only after it is filled, e.g. when we understand the the row we printed is the
    824  *    last for certain logic
    825  */
    826 #define PRT_ROW_SET_MODE(mc_mode)       _PRT_ROW_SET_MODE(prt_ctr, mc_mode)
    827 
    828 /**
    829  * \brief Add new row in the table
    830  * \par DIRECT INPUT
    831  * \param [in] mc_mode Points to the type of separator from previous line. See PRT_ROW_SEP_MODE
    832  * \par INDIRECT INPUT prt_list - pointer to the list of rows, that this one will be added to
    833  *                     prt_row_offset - current place in the row to be written (cell pointer)
    834  *                     prt_row_start - pointer to the beginning of row
    835  * \par INDIRECT OUTPUT prt_list - new row will be added to this list
    836  *                      prt_row_start - pointer to the beginning of new row
    837  *                      prt_row_offset - set to the beginning of new row skipping control info
    838  * \remark First row filled followed by ROW_COLUMN_SET is considered of being header one
    839  */
    840 #define PRT_ROW_ADD(mc_mode)            _PRT_ROW_ADD(prt_ctr, mc_mode)
    841 
    842 /**
    843  * \brief Add new row in the table
    844  * \remark Last row in the table to be deleted due to lack of interest in its content
    845  */
    846 #define PRT_ROW_DELETE()            _PRT_ROW_DELETE(prt_ctr)
    847 
    848 /**
    849  * \brief
    850  *    Returns current row number, is useful to figure out if there were rows at all and how many of them
    851  */
    852 #define PRT_ROW_NUM()               _PRT_ROW_NUM(prt_ctr)
    853 
    854 /**
    855  * \brief Fill cell with formatted data
    856  * \par INDIRECT OUTPUT prt_ctr_mc->col_cur is updated, so to reflect that cell was filled
    857  * \remark
    858  *    1. Maximum size of regular cell is PRT_COLUMN_WIDTH - 1
    859  *    2. In the case of flexible column size may be up to PRT_COLUMN_WIDTH_BIG - 1
    860  *    3. So cell with length between these 2 values will be split either accordingly - see PRT_COLUMN_ADD_FLEX
    861  */
    862 #define PRT_CELL_SET(...)               _PRT_CELL_SET(prt_ctr, __VA_ARGS__)
    863 /**
    864  * \brief same as PRT_CELL_SET with only difference being shift inside the cell for indentation purposes
    865  * \param [in] prt_n - number of shift in the cell, each shift is 2 spaces
    866  * \par INDIRECT OUTPUT prt_ctr_mc->col_cur is updated, so to reflect that cell was filled
    867  * \remark
    868  *    Used when we don't want to add additional column, but rather indent certain places in the same column
    869  */
    870 #define PRT_CELL_SET_SHIFT(prt_n, ...)  _PRT_CELL_SET_SHIFT(prt_ctr, prt_n, __VA_ARGS__)
    871 
    872 /**
    873  * \brief When filling table allows to skip cell
    874  * \param [in] mc_skip_num - number of cells to be skipped
    875  * \par INDIRECT OUTPUT prt_ctr_mc->col_cur is updated, so to reflect that cell was filled
    876  * \remark
    877  *     No need to do SKIP at the end of ROW, anyway new row will start from column
    878  */
    879 #define PRT_CELL_SKIP(mc_skip_num)      _PRT_CELL_SKIP(prt_ctr, mc_skip_num)
    880 
    881 /**
    882  * \brief Actual printing of prepared data, may be used inside or outside framework
    883  * \remark
    884  *    Does not support XML output, see PRT_COMMITF for XML output outside framework
    885  */
    886 #define PRT_COMMIT                      _PRT_COMMIT(prt_ctr)
    887 
    888 /**
    889  * \brief Actual printing of prepared data to be used only in the context of shell framework
    890  * \remark
    891  *    Requires presence of sand_control, which is implicitly provided by the shell command invocation parameters, and
    892  *    should be transfered to underlying routines in the case of PRT usage down stack.
    893  *    This macro allows to transfer implicitly cli options to PRT - e.g XML file output
    894  *    Frees the list
    895  */
    896 #define PRT_COMMITX                     _PRT_COMMITX(prt_ctr)
    897 
    898 /**
    899  * \brief Actual printing of prepared data to be used, when outside shell framework XML file output may be requested
    900  * \param [in] filename_str - XML file to be used for data export, if NULL the one from sand_control may be used
    901  * \remark
    902  *    Requires presence of sand_control, which is implicitly provided by the shell command invocation parameters, and
    903  *    should be transfered to underlying routines in the case of PRT usage down stack.
    904  *    This macro allows to transfer implicitly cli options to PRT - e.g XML file output
    905  *    Frees the list
    906  */
    907 #define PRT_COMMITF(filename_str)       _PRT_COMMITF(prt_ctr, filename_str)
    908 
    909 /**
    910  * \brief Free control structure allocated by SET_TITLE
    911  * \remark
    912  *     Should be always used at the end(usually after exit: label) of routine using pretty printing to catch all errors
    913  */
    914 #define PRT_FREE                        _PRT_FREE(prt_ctr)
    915 /*
    916  * End of facilities for external usage when only 1 table is required
    917  * }
    918  */
    919 
    920 /*
    921  * Below MACROs are for external usage when only Simultaneous Multiple Table are required
    922  * All MACROs below will have _PL (plural) as a mark for this purpose
    923  * All MACROS are exactly the same as regular ones with the only difference being additional parameter of table id
    924  * {
    925  */
    926 /**
    927  * \brief Declares pointer to control structure used by pretty printing
    928  * \param [in] mc_num - number of tables required for simultaneous filling
    929  */
    930 #define PRT_INIT_VARS_PL(mc_num)            prt_control_t *prt_ctr[mc_num] = {NULL}
    931 
    932 /**
    933  * All MACROS are exactly the same as regular ones with the only difference being additional parameter of table mc_id
    934  * See one table macros for description
    935  */
    936 #define PRT_TITLE_SET_PL(mc_id, ...)             _PRT_TITLE_SET(prt_ctr[mc_id], __VA_ARGS__)
    937 #define PRT_INFO_ADD_PL(mc_id, ...)              _PRT_INFO_ADD(prt_ctr[mc_id], __VA_ARGS__)
    938 #define PRT_COLUMN_ADD_PL(mc_id, ...)                                                                                  \
    939                         _PRT_COLUMN_ADD(prt_ctr[mc_id], PRT_FLEX_NONE, PRT_COLUMN_WIDTH, __VA_ARGS__)
    940 #define PRT_COLUMN_ADD_FLEX_PL(mc_id, flag, ...)                                                                       \
    941                         _PRT_COLUMN_ADD(prt_ctr[mc_id], flag, PRT_COLUMN_WIDTH_BIG, __VA_ARGS__)
    942 #define PRT_COLUMN_ADDX_PL(mc_id, prt_type, prt_parent_id, prt_my_id_ptr, ...) \
    943                         _PRT_COLUMN_ADDX(prt_ctr[mc_id], prt_type, prt_parent_id, prt_my_id_ptr, __VA_ARGS__)
    944 #define PRT_COLUMN_ADDX_FLEX_PL(mc_id, flag, prt_type, prt_parent_id, prt_my_id_ptr, ...)                              \
    945                         _PRT_COLUMN_ADDX_FLEX(prt_ctr[mc_id], flag, prt_type, prt_parent_id, prt_my_id_ptr, __VA_ARGS__)
    946 #define PRT_COLUMN_NUM_PL(mc_id)                 _PRT_COLUMN_NUM(prt_ctr[mc_id])
    947 #define PRT_ROW_SET_MODE_PL(mc_id, mc_mode)      _PRT_ROW_SET_MODE(prt_ctr[mc_id], mc_mode)
    948 #define PRT_ROW_ADD_PL(mc_id, mc_mode)           _PRT_ROW_ADD(prt_ctr[mc_id], mc_mode)
    949 #define PRT_ROW_NUM_PL(mc_id)                    _PRT_ROW_NUM(prt_ctr[mc_id])
    950 #define PRT_CELL_SET_PL(mc_id, ...)              _PRT_CELL_SET(prt_ctr[mc_id], __VA_ARGS__)
    951 #define PRT_CELL_SET_SHIFT_PL(mc_id, prt_n, ...) _PRT_CELL_SET_SHIFT(prt_ctr[mc_id], prt_n, __VA_ARGS__)
    952 #define PRT_CELL_SKIP_PL(mc_id, mc_skip_num)     _PRT_CELL_SKIP(prt_ctr[mc_id], mc_skip_num)
    953 #define PRT_COMMIT_PL(mc_id)                     _PRT_COMMIT(prt_ctr[mc_id])
    954 #define PRT_COMMITX_PL(mc_id)                    _PRT_COMMITX(prt_ctr[mc_id])
    955 #define PRT_COMMITF_PL(mc_id, filename_str)      _PRT_COMMITF(prt_ctr[mc_id], filename_str)
    956 #define PRT_FREE_PL(mc_id)                       _PRT_FREE(prt_ctr[mc_id])
    957 
    958 #define PRT_COMMITX_COMBINE_PL(mc_num)         _PRT_COMMITX_COMBINE(prt_ctr, mc_num)
    959 /*
    960  * End of facilities for external usage for multiple tables
    961  * }
    962  */
    963 
    964 #endif /* DIAG_SAND_PRT_H */