data_interpretor.c

Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 3; indent-tabs-mode: t; c-basic-offset: 3 -*- */
00002 /*
00003   data_interpretor.c
00004   heraia - an hexadecimal file editor and analyser based on ghex
00005 
00006   (C) Copyright 2005 - 2010 Olivier Delhomme
00007   e-mail : heraia@delhomme.org
00008   URL    : http://heraia.tuxfamily.org
00009 
00010   This program is free software; you can redistribute it and/or modify
00011   it under the terms of the GNU General Public License as published by
00012   the Free Software Foundation; either version 2, or  (at your option)
00013   any later version.
00014 
00015   This program is distributed in the hope that it will be useful,
00016   but WITHOUT ANY WARRANTY;  without even the implied warranty of
00017   MERCHANTABILITY  or  FITNESS FOR A PARTICULAR PURPOSE.  See the
00018   GNU General Public License for more details.
00019 
00020   You should have received a copy of the GNU General Public License
00021   along with this program; if not, write to the Free Software
00022   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
00023 /**
00024  * @file data_interpretor.c
00025  * Here one may find tools to manage the data_interpretor window
00026  */
00027 #include <libheraia.h>
00028 
00029 static guint which_endianness(heraia_struct_t *main_struct);
00030 static guint which_stream_size(heraia_struct_t *main_struct);
00031 static void interpret(doc_t *doc, decode_t *decode_struct, decode_parameters_t *decode_parameters, guint length);
00032 static void close_data_interpretor_window(GtkWidget *widget, gpointer data);
00033 static void connect_data_interpretor_signals(heraia_struct_t *main_struct);
00034 static void refresh_one_row(doc_t *doc, decode_generic_t *row,  guint nb_cols, decode_parameters_t *decode_parameters);
00035 static void refresh_one_tab(doc_t *doc, data_window_t *dw, tab_t *tab, decode_parameters_t *decode_parameters);
00036 static void refresh_all_tabs(doc_t *doc, data_window_t *dw, decode_parameters_t *decode_parameters);
00037 static void add_default_tabs(heraia_struct_t *main_struct);
00038 
00039 
00040 /**
00041  * @fn guint which_endianness(heraia_struct_t *main_struct)
00042  *  Determines which endianness is selected that is to say
00043  *  which radio button is active in the window
00044  * @param main_struct : main structure
00045  * @return Something of the following, depending on what selected the user :
00046  *         - H_DI_LITTLE_ENDIAN for little endian encoding (default answer)
00047  *         - H_DI_BIG_ENDIAN for big endian encoding
00048  *         - H_DI_MIDDLE_ENDIAN for middle endian encoding
00049  */
00050 static guint which_endianness(heraia_struct_t *main_struct)
00051 {
00052     GtkRadioButton *rb = GTK_RADIO_BUTTON(heraia_get_widget(main_struct->xmls->main, "diw_rb_little_endian"));
00053     GtkWidget *activated = NULL;
00054     const gchar *widget_name = NULL;
00055 
00056     activated = gtk_radio_button_get_active_from_widget(rb);
00057     widget_name = gtk_widget_get_name(activated);
00058 
00059     if (g_ascii_strcasecmp(widget_name, "diw_rb_little_endian") == 0)
00060         {
00061             return H_DI_LITTLE_ENDIAN;
00062         }
00063     else if (g_ascii_strcasecmp(widget_name, "diw_rb_big_endian") == 0)
00064         {
00065             return H_DI_BIG_ENDIAN;
00066         }
00067     else if (g_ascii_strcasecmp(widget_name, "diw_rb_middle_endian") == 0)
00068         {
00069             return H_DI_MIDDLE_ENDIAN;
00070         }
00071     else
00072         return H_DI_LITTLE_ENDIAN;  /* default interpretation case */
00073 }
00074 
00075 
00076 /**
00077  * returns stream size as selected in the spin button
00078  * @param main_struct : main structure
00079  * @return returns the value of the spin button or 1 if this value is not valid
00080  */
00081 static guint which_stream_size(heraia_struct_t *main_struct)
00082 {
00083     GtkWidget *spin_button = NULL;
00084     guint stream_size = 1;
00085 
00086     spin_button = heraia_get_widget(main_struct->xmls->main, "stream_size_spin_button");
00087 
00088     stream_size = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_button));
00089 
00090     if (stream_size >= 1)
00091         {
00092             return stream_size;
00093         }
00094     else
00095         {
00096             return 1;
00097         }
00098 }
00099 
00100 
00101 /**
00102  *   Here we do interpret a something according to the decode_it function and we
00103  *   write down the result in a widget designated "entry"
00104  *  @warning We are assuming that main_struct != NULL and main_struct->xml != NULL
00105  *
00106  *  @param main_struct : main structure
00107  *  @param decode : a decode_t structure that contains function, entry and error message
00108  *  @param decode_parameters : structure that passes some arguments to the
00109  *            decoding functions
00110  *  @param length : the length of the data to be decoded (guint)
00111  */
00112 static void interpret(doc_t *doc, decode_t *decode_struct, decode_parameters_t *decode_parameters, guint length)
00113 {
00114     gint result = 0;    /** used to test different results of function calls                            */
00115     guchar *c = NULL;   /** the character under the cursor                                              */
00116     gchar *text = NULL; /** decoded text                                                                */
00117     DecodeFunc decode_it = NULL; /** A DecodeFunc which is a function to be called to decode the stream */
00118 
00119     c = (guchar *) g_malloc0(sizeof(guchar) * length);
00120 
00121     result = ghex_get_data(doc->hex_widget, length, decode_parameters->endianness, c);
00122 
00123     if (result == TRUE)
00124         {
00125             decode_it = decode_struct->func;
00126 
00127             text = decode_it(c, (gpointer) decode_parameters);
00128 
00129             if (text != NULL)
00130                 {
00131                     gtk_entry_set_text(GTK_ENTRY(decode_struct->entry), text);
00132                 }
00133             else
00134                 {
00135                     text = g_strdup_printf("Something's wrong!");
00136                     gtk_entry_set_text(GTK_ENTRY(decode_struct->entry), text);
00137                 }
00138         }
00139     else
00140         {
00141             if (decode_struct->err_msg != NULL)
00142                 {
00143                     text = g_strdup_printf(decode_struct->err_msg, length);
00144                 }
00145             else
00146                 {
00147                     text = g_strdup_printf("Cannot interpret as a %d byte(s)", length);
00148                 }
00149 
00150             gtk_entry_set_text(GTK_ENTRY(decode_struct->entry), text);
00151         }
00152 
00153     g_free(c);
00154     g_free(text);
00155 }
00156 
00157 
00158 /**
00159  * @fn void close_data_interpretor_window(GtkWidget *widget, gpointer data)
00160  *  "Emulates" the user click on the main window menu entry called DIMenu
00161  *  whose aim is to display or hide the data interpretor window
00162  * @param widget : the widget caller (may be NULL here)
00163  * @param data : a gpointer to the main structure : main_struct, this must NOT
00164  *        be NULL !
00165  */
00166 static void close_data_interpretor_window(GtkWidget *widget, gpointer data)
00167 {
00168     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00169 
00170     if (main_struct != NULL && main_struct->xmls != NULL  && main_struct->xmls->main)
00171         {
00172             g_signal_emit_by_name(heraia_get_widget(main_struct->xmls->main, "DIMenu"), "activate");
00173         }
00174 }
00175 
00176 
00177 /**
00178  * This function refreshes one row of the tab
00179  * @param dw : current data window
00180  * @param row : the row that we want to refresh
00181  * @param nb_cols : number of columns in this particular row (this IS the same
00182  *                  for all rows in that tab
00183  * @param decode_parameters : structure that passes some arguments to the
00184  *        decoding functions
00185  */
00186 static void refresh_one_row(doc_t *doc, decode_generic_t *row,  guint nb_cols, decode_parameters_t *decode_parameters)
00187 {
00188     decode_t *decode = NULL;   /**< entry, function and message */
00189     guint i = 0 ;
00190 
00191     while ( i < nb_cols)
00192         {
00193             decode = g_ptr_array_index(row->decode_array, i);
00194 
00195             if (row->fixed_size == FALSE)
00196                 {
00197                     row->data_size = decode_parameters->stream_size;
00198                 }
00199 
00200             interpret(doc, decode, decode_parameters, row->data_size);
00201             i++;
00202         }
00203 }
00204 
00205 
00206 /**
00207  * This function refreshes one entire tab (row by row)
00208  * @param dw : current data window
00209  * @param tab : the tab to refresh
00210  * @param decode_parameters : structure that passes some arguments to the
00211  *        decoding functions
00212  */
00213 static void refresh_one_tab(doc_t *doc, data_window_t *dw, tab_t *tab, decode_parameters_t *decode_parameters)
00214 {
00215     decode_generic_t *row = NULL; /**< the row we want to refresh */
00216     guint i = 0;
00217 
00218     while (i < tab->nb_rows)
00219         {
00220             row = g_ptr_array_index(tab->rows, i);
00221             refresh_one_row(doc, row, tab->nb_cols-1, decode_parameters);
00222             i++;
00223         }
00224 }
00225 
00226 
00227 /**
00228  * Refreshes all tabs
00229  * @param dw : current data window
00230  * @param decode_parameters : structure that passes some arguments to the
00231  *        decoding functions
00232  */
00233 static void refresh_all_tabs(doc_t *doc, data_window_t *dw, decode_parameters_t *decode_parameters)
00234 {
00235     tab_t *tab = NULL;
00236     guint i = 0;
00237 
00238     while (i < dw->nb_tabs)
00239         {
00240             tab = g_ptr_array_index(dw->tabs, i);
00241             refresh_one_tab(doc, dw, tab, decode_parameters);
00242             i++;
00243         }
00244 
00245 }
00246 
00247 
00248 /**
00249  * @fn void refresh_data_interpretor_window(GtkWidget *widget, gpointer data)
00250  *  Refreshes the data interpretor window with the new values
00251  * @param widget : the widget caller (may be NULL here)
00252  * @param data : a gpointer to the main structure : main_struct, this must NOT
00253  *        be NULL !
00254  * @todo if speed is a matter, think about taking off this decode_parameters
00255  *       structure from here.
00256  */
00257 void refresh_data_interpretor_window(GtkWidget *widget, gpointer data)
00258 {
00259     heraia_struct_t *main_struct = (heraia_struct_t *) data;  /** data interpretor window structure */
00260     decode_parameters_t *decode_parameters = NULL;
00261     guint endianness = 0;
00262     guint stream_size = 0;
00263 
00264     if (main_struct != NULL &&
00265         main_struct->current_doc != NULL &&
00266         main_struct->current_DW != NULL &&
00267         main_struct->win_prop->main_dialog->displayed == TRUE)
00268         {
00269             endianness = which_endianness(main_struct);    /** Endianness is computed only once here  */
00270             stream_size =  which_stream_size(main_struct); /** stream size is computed only once here */
00271 
00272             decode_parameters = new_decode_parameters_t(endianness, stream_size);
00273 
00274             refresh_all_tabs(main_struct->current_doc, main_struct->current_DW, decode_parameters);
00275 
00276             g_free(decode_parameters);
00277         }
00278 }
00279 
00280 
00281 /**
00282  * @fn void connect_data_interpretor_signals(heraia_struct_t *main_struct)
00283  *  Connects data interpretor window's signals to the
00284  *  right functions
00285  * @param main_struct : main structure
00286  */
00287 static void connect_data_interpretor_signals(heraia_struct_t *main_struct)
00288 {
00289     /* When data interpretor's window is killed or destroyed */
00290     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "data_interpretor_window")), "delete_event",
00291                      G_CALLBACK(delete_dt_window_event), main_struct);
00292 
00293     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "data_interpretor_window")), "destroy",
00294                      G_CALLBACK(destroy_dt_window), main_struct);
00295 
00296     /* Radio Button "Little Endian" */
00297     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "diw_rb_little_endian")), "toggled",
00298                      G_CALLBACK(refresh_data_interpretor_window), main_struct);
00299 
00300     /* Radio Button "Big Endian" */
00301     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "diw_rb_big_endian")), "toggled",
00302                      G_CALLBACK(refresh_data_interpretor_window), main_struct);
00303 
00304     /* Radio Button "Middle Endian" */
00305     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "diw_rb_middle_endian")), "toggled",
00306                      G_CALLBACK(refresh_data_interpretor_window), main_struct);
00307 
00308     /* Spin button */
00309     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "stream_size_spin_button")), "value-changed",
00310                      G_CALLBACK(refresh_data_interpretor_window), main_struct);
00311 
00312 }
00313 
00314 
00315 /**
00316  * @fn void data_interpretor_init_interface(heraia_struct_t *main_struct)
00317  *  Inits the data interpretor structure and window with default values
00318  *  @warning Should be called only once at program's beginning
00319  */
00320 void data_interpretor_init_interface(heraia_struct_t *main_struct)
00321 {
00322     data_window_t *dw = NULL;
00323 
00324     if (main_struct != NULL)
00325         {
00326             /* Signals connections */
00327             connect_data_interpretor_signals(main_struct);
00328 
00329             dw = main_struct->current_DW;
00330 
00331             if (dw != NULL)
00332                 {
00333                     dw->diw = heraia_get_widget(main_struct->xmls->main, "data_interpretor_window");
00334 
00335                     /* Here init all defaults tabs */
00336                     add_default_tabs(main_struct);
00337                 }
00338         }
00339 }
00340 
00341 
00342 /**
00343  * Adds a new tab in the data interpretor window
00344  * @param notebook : the notebook to which we want to add this new tab
00345  * @param index : index of this new tab. If you rely on this make sure it's
00346  *                a primary key !
00347  * @param label : label of the tab
00348  * @param nb_cols : number of columns (including the first column of labels)
00349  * @param ... : nb_cols arguments that will be the labels of the columns
00350  */
00351 tab_t *add_new_tab_in_data_interpretor(GtkNotebook *notebook, guint index, gchar *label, guint nb_cols, ...)
00352 {
00353     tab_t *tab = NULL;            /**< tab structure that will remember everything !                     */
00354     va_list args;                 /**< va_list arguments passed to create a new tab with those columns   */
00355     guint i = 0;
00356     gchar *col_label = NULL;      /**< used to fetch atguments                                           */
00357     GPtrArray *col_labels = NULL; /**< used to remember the columns labels (the arguments in GtkWidgets) */
00358     GPtrArray *vboxes = NULL;     /**< used to remember vboxes (in order to be able to pack things later */
00359     GtkWidget *child = NULL;      /**< notebook tab's child container                                    */
00360     GtkWidget *hpaned = NULL;     /**< used for hpaned creation                                          */
00361     GtkWidget *hpaned2 = NULL;    /**< in case that we have more than 2 arguments                        */
00362     GtkWidget *vbox = NULL;       /**< used for vbox creation                                            */
00363     GtkWidget *vbox_label = NULL; /**< used for label creation in the new vboxes                         */
00364 
00365     col_labels = g_ptr_array_new();
00366     vboxes = g_ptr_array_new();
00367 
00368     va_start(args, nb_cols);
00369     for (i = 0 ; i < nb_cols ; i++)
00370         {
00371             col_label = (gchar *) va_arg(args, int);
00372             vbox_label = gtk_label_new(col_label);
00373             gtk_misc_set_padding(GTK_MISC(vbox_label), 3, 3);       /* properties for the labels */
00374             gtk_misc_set_alignment(GTK_MISC(vbox_label), 0.5, 0.5);
00375             g_ptr_array_add(col_labels, (gpointer) vbox_label);
00376         }
00377     va_end(args);
00378 
00379     tab = (tab_t *) g_malloc0(sizeof(tab_t));
00380 
00381     i = 0;
00382     hpaned = gtk_hpaned_new();
00383     gtk_container_set_border_width(GTK_CONTAINER(hpaned), 2); /* properties for the hpaned */
00384     child = hpaned;
00385     vbox = gtk_vbox_new(FALSE, 2);
00386     gtk_box_set_homogeneous(GTK_BOX(vbox), FALSE);
00387     g_ptr_array_add(vboxes, vbox);
00388     gtk_paned_add1(GTK_PANED(hpaned), (gpointer) vbox);
00389     vbox_label = g_ptr_array_index(col_labels, i);
00390     gtk_box_pack_start(GTK_BOX(vbox), vbox_label, FALSE, FALSE, 3);
00391 
00392     i++;
00393     while (i < nb_cols-1)
00394         {
00395             hpaned2 = gtk_hpaned_new();
00396             gtk_container_set_border_width(GTK_CONTAINER(hpaned2), 2); /* properties for the hpaned */
00397             gtk_paned_add2(GTK_PANED(hpaned), hpaned2);
00398             hpaned = hpaned2;                  /* translation */
00399             vbox = gtk_vbox_new(FALSE, 2);
00400             gtk_box_set_homogeneous(GTK_BOX(vbox), FALSE);
00401             g_ptr_array_add(vboxes, (gpointer) vbox);
00402             gtk_paned_add1(GTK_PANED(hpaned), vbox);
00403             vbox_label = g_ptr_array_index(col_labels, i);
00404             gtk_box_pack_start(GTK_BOX(vbox), vbox_label, FALSE, FALSE, 3);
00405             i++;
00406         }
00407 
00408     vbox = gtk_vbox_new(FALSE, 2);
00409     g_ptr_array_add(vboxes, (gpointer) vbox);
00410     gtk_paned_add2(GTK_PANED(hpaned), vbox);
00411     gtk_box_set_homogeneous(GTK_BOX(vbox), FALSE);
00412     vbox_label = g_ptr_array_index(col_labels, i);
00413     gtk_box_pack_start(GTK_BOX(vbox), vbox_label, FALSE, FALSE, 3);
00414 
00415     tab->index = index;
00416     tab->nb_cols = nb_cols;
00417     tab->nb_rows = 0;
00418     tab->label = gtk_label_new(label);   /* tab's label */
00419     gtk_misc_set_padding(GTK_MISC(tab->label), 2, 2);
00420     gtk_misc_set_alignment(GTK_MISC(tab->label), 0.5, 0.5);
00421     tab->col_labels = col_labels;
00422     tab->vboxes = vboxes;
00423     tab->rows = NULL;
00424 
00425     gtk_widget_show_all(child);
00426     gtk_notebook_append_page(notebook, child, tab->label);
00427 
00428     return tab;
00429 }
00430 
00431 
00432 /**
00433  * Adds a row to a particular tab
00434  * @param tab : the tab to which we want to add the row
00435  * @param row : the row we want to add (make sure it has been initialized)
00436  */
00437 void add_new_row_to_tab(tab_t *tab, decode_generic_t *row)
00438 {
00439     GtkWidget *vbox = NULL;  /**< the vbox to which we want to pack           */
00440     decode_t *couple = NULL; /**< couple from which we want to pack the entry */
00441     guint i = 0;
00442     guint j = 0;
00443 
00444     if (tab != NULL && row != NULL)
00445         {
00446 
00447             if (tab->rows == NULL)
00448                 {
00449                     tab->rows = g_ptr_array_new();
00450                 }
00451 
00452             g_ptr_array_add(tab->rows, (gpointer) row);
00453             tab->nb_rows++;
00454 
00455             /* label packing */
00456             vbox = g_ptr_array_index(tab->vboxes, 0);
00457             gtk_box_pack_start(GTK_BOX(vbox), row->label, FALSE, FALSE, 3);
00458 
00459             j = 0;
00460             i = 1;
00461 
00462             while (i <  tab->nb_cols)
00463                 {
00464                     vbox = g_ptr_array_index(tab->vboxes, i);
00465                     couple = g_ptr_array_index(row->decode_array, j);
00466                     gtk_box_pack_start(GTK_BOX(vbox), couple->entry, FALSE, FALSE, 1);
00467                     gtk_widget_show(couple->entry);
00468                     j++;
00469                     i++;
00470                 }
00471         }
00472 }
00473 
00474 
00475 /**
00476  * Inits data interpretor with default tabs
00477  * Must be called only once at bootime
00478  * @param main_struct : main_structure
00479  * */
00480 static void add_default_tabs(heraia_struct_t *main_struct)
00481 {
00482     GtkWidget *notebook = NULL;
00483     tab_t *tab = NULL;
00484     decode_generic_t *row = NULL;
00485     data_window_t *dw = NULL;
00486 
00487     dw = main_struct->current_DW;
00488     notebook = heraia_get_widget(main_struct->xmls->main, "diw_notebook");
00489 
00490     dw->tabs = g_ptr_array_new();
00491 
00492     /** Adding a tab for numbers */
00493     tab = add_new_tab_in_data_interpretor(GTK_NOTEBOOK(notebook), 0, "Numbers", 3, "Length", "Value unsigned", "Value signed");
00494 
00495     if (tab != NULL)
00496         {
00497             g_ptr_array_add(dw->tabs, (gpointer) tab);
00498             dw->nb_tabs++;
00499             row = new_decode_generic_t("8 bits", 1, TRUE, "Can not interpret %d byte as a 8 bits number", 2,  decode_8bits_unsigned, decode_8bits_signed);
00500             add_new_row_to_tab(tab, row);
00501             row = new_decode_generic_t("16 bits", 2, TRUE, "Can not interpret %d bytes as a 16 bits number", 2, decode_16bits_unsigned, decode_16bits_signed);
00502             add_new_row_to_tab(tab, row);
00503             row = new_decode_generic_t("32 bits", 4, TRUE, "Can not interpret %d bytes as a 32 bits number", 2, decode_32bits_unsigned, decode_32bits_signed);
00504             add_new_row_to_tab(tab, row);
00505             row = new_decode_generic_t("64 bits", 8, TRUE, "Can not interpret %d bytes as a 64 bits number", 2, decode_64bits_unsigned, decode_64bits_signed);
00506             add_new_row_to_tab(tab, row);
00507         }
00508 
00509     /** Adding a tab for floting numbers */
00510     tab = add_new_tab_in_data_interpretor(GTK_NOTEBOOK(notebook), 0, "Floats", 3, "Length", "Normal Notation", "Exponential notation");
00511 
00512     if (tab != NULL)
00513         {
00514             g_ptr_array_add(dw->tabs, (gpointer) tab);
00515             dw->nb_tabs++;
00516             row = new_decode_generic_t("Float (32 bits)", 4, TRUE, "Can not interpret %d bytes as a float number", 2, decode_float_normal, decode_float_scientific);
00517             add_new_row_to_tab(tab, row);
00518             row = new_decode_generic_t("Double (64 bits)", 8, TRUE, "Can not interpret %d bytes as a double number", 2, decode_double_normal, decode_double_scientific);
00519             add_new_row_to_tab(tab, row);
00520         }
00521 
00522     /** Adding a tab for date and time */
00523     tab = add_new_tab_in_data_interpretor(GTK_NOTEBOOK(notebook), 2, "Dates and Times", 2, "Type", "Value");
00524 
00525     if (tab != NULL)
00526         {
00527             g_ptr_array_add(dw->tabs, (gpointer) tab);
00528             dw->nb_tabs++;
00529             row = new_decode_generic_t("MS-DOS", 4, TRUE, "Can not interpret %d bytes as a DOS date", 1, decode_dos_date);
00530             add_new_row_to_tab(tab, row);
00531             row = new_decode_generic_t("Filetime", 8, TRUE,  "Can not interpret %d bytes as a filetime date", 1, decode_filetime_date);
00532             add_new_row_to_tab(tab, row);
00533             row = new_decode_generic_t("C", 4, TRUE, "Can not interpret %d bytes as a C date", 1, decode_C_date);
00534             add_new_row_to_tab(tab, row);
00535             row = new_decode_generic_t("HFS", 4, TRUE, "Can not interpret %d bytes as a HFS date",  1, decode_HFS_date);
00536             add_new_row_to_tab(tab, row);
00537         }
00538 
00539     /** Adding a tab for binary based conversions */
00540     tab = add_new_tab_in_data_interpretor(GTK_NOTEBOOK(notebook), 3, "Binary based", 2, "Type", "Value");
00541 
00542     if (tab != NULL)
00543         {
00544             g_ptr_array_add(dw->tabs, (gpointer) tab);
00545             dw->nb_tabs++;
00546             row = new_decode_generic_t("Bits", 1, FALSE, "Can not decode %d byte(s) to bits", 1, decode_to_bits);
00547             add_new_row_to_tab(tab, row);
00548             row = new_decode_generic_t("Packed BCD", 1, FALSE, "Can not interpret %d byte(s) as packed BCD string",  1, decode_packed_BCD);
00549             add_new_row_to_tab(tab, row);
00550         }
00551 }
00552 
00553 
00554 
00555 
00556 
00557 
00558 
00559 
00560 
00561 
00562 
00563 
00564 
00565 
00566 
00567 
00568 
00569 
Generated on Tue May 11 18:46:08 2010 for Heraia by  doxygen 1.6.3