Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

  1. /* chartrans.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS                                                                        */
  6. /*                                                                           */
  7. /* Character Translation                                                     */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <errno.h>
  13. #include <string.h>
  14. #include "nonzstring.h"
  15. #include "asmerr.h"
  16. #include "chartrans.h"
  17.  
  18. static void clr_mapped(as_chartrans_table_t *p_table, unsigned code)
  19. {
  20.   p_table->mapped[code >> 3] &= ~(1 << (code & 7));
  21. }
  22.  
  23. static void set_mapped(as_chartrans_table_t *p_table, unsigned code)
  24. {
  25.   p_table->mapped[code >> 3] |= 1 << (code & 7);
  26. }
  27.  
  28. static Boolean is_mapped(const as_chartrans_table_t *p_table, unsigned code)
  29. {
  30.   return (p_table->mapped[code >> 3] >> (code & 7)) & 1;
  31. }
  32.  
  33. /*!------------------------------------------------------------------------
  34.  * \fn     as_chartrans_table_new(void)
  35.  * \brief  allocate new table
  36.  * \return * to table or NULL
  37.  * ------------------------------------------------------------------------ */
  38.  
  39. as_chartrans_table_t *as_chartrans_table_new(void)
  40. {
  41.   as_chartrans_table_t *p_ret = (as_chartrans_table_t*)calloc(1, sizeof(*p_ret));
  42.   if (p_ret)
  43.     as_chartrans_table_reset(p_ret);
  44.   return p_ret;
  45. }
  46.  
  47. /*!------------------------------------------------------------------------
  48.  * \fn     as_chartrans_table_free(as_chartrans_table_t *p_table)
  49.  * \brief  deallocate table
  50.  * \param  p_table table to free
  51.  * ------------------------------------------------------------------------ */
  52.  
  53. void as_chartrans_table_free(as_chartrans_table_t *p_table)
  54. {
  55.   if (p_table)
  56.     free(p_table);
  57. }
  58.  
  59. /*!------------------------------------------------------------------------
  60.  * \fn     as_chartrans_table_dup(const as_chartrans_table_t *p_table)
  61.  * \brief  duplicate table
  62.  * \param  p_table origin
  63.  * \return duplicate or NULL
  64.  * ------------------------------------------------------------------------ */
  65.  
  66. as_chartrans_table_t *as_chartrans_table_dup(const as_chartrans_table_t *p_table)
  67. {
  68.   as_chartrans_table_t *p_ret = NULL;
  69.  
  70.   if (!p_table)
  71.     return p_ret;
  72.  
  73.   p_ret = (as_chartrans_table_t*)calloc(1, sizeof(*p_ret));
  74.   memcpy(p_ret->mapped, p_table->mapped, sizeof(p_ret->mapped));
  75.   memcpy(p_ret->mapping, p_table->mapping, sizeof(p_ret->mapping));
  76.   return p_ret;
  77. }
  78.  
  79. /*!------------------------------------------------------------------------
  80.  * \fn     void as_chartrans_table_reset(as_chartrans_table_t *p_table)
  81.  * \brief  reset table to default
  82.  * \param  p_table table to reset
  83.  * ------------------------------------------------------------------------ */
  84.  
  85. void as_chartrans_table_reset(as_chartrans_table_t *p_table)
  86. {
  87.   unsigned z;
  88.  
  89.   for (z = 0; z < 256; z++)
  90.     p_table->mapping[z] = z;
  91.   memset(p_table->mapped, 0xff, sizeof(p_table->mapped));
  92. }
  93.  
  94. /*!------------------------------------------------------------------------
  95.  * \fn     as_chartrans_table_set(as_chartrans_table_t *p_table, unsigned input_code, unsigned output_code)
  96.  * \brief  change translation entry
  97.  * \param  p_table table to update
  98.  * \param  input_code new source value
  99.  * \param  output_code new translated value
  100.  * \return 0 if success
  101.  * ------------------------------------------------------------------------ */
  102.  
  103. int as_chartrans_table_set(as_chartrans_table_t *p_table, unsigned input_code, unsigned output_code)
  104. {
  105.   if ((input_code > 255) || (output_code > 255))
  106.     return E2BIG;
  107.   set_mapped(p_table, input_code);
  108.   p_table->mapping[input_code] = output_code;
  109.   return 0;
  110. }
  111.  
  112. /*!------------------------------------------------------------------------
  113.  * \fn     as_chartrans_table_unset(as_chartrans_table_t *p_table, unsigned input_code)
  114.  * \brief  invalidate translation entry
  115.  * \param  p_table table to update
  116.  * \param  input_code new source value
  117.  * \return 0 if success
  118.  * ------------------------------------------------------------------------ */
  119.  
  120. int as_chartrans_table_unset(as_chartrans_table_t *p_table, unsigned input_code)
  121. {
  122.   if (input_code > 255)
  123.     return E2BIG;
  124.   clr_mapped(p_table, input_code);
  125.   p_table->mapping[input_code] = 0;
  126.   return 0;
  127. }
  128.  
  129. /*!------------------------------------------------------------------------
  130.  * \fn     as_chartrans_table_set_mult(as_chartrans_table_t *p_table, unsigned input_code_from, unsigned input_code_to, unsigned output_code)
  131.  * \brief  change translation entry block
  132.  * \param  p_table table to update
  133.  * \param  input_code_from new source start value
  134.  * \param  input_code_to new source end value (inclusive)
  135.  * \param  output_code new translated value
  136.  * \return 0 if success
  137.  * ------------------------------------------------------------------------ */
  138.  
  139. int as_chartrans_table_set_mult(as_chartrans_table_t *p_table, unsigned input_code_from, unsigned input_code_to, unsigned output_code)
  140. {
  141.   if (input_code_from > input_code_to)
  142.     return EBADF;
  143.   if ((input_code_from > 255) || (input_code_to > 255)
  144.    || (output_code > 255) || (output_code + (input_code_to - input_code_from - 1) > 255))
  145.     return E2BIG;
  146.   for (; input_code_from <= input_code_to; input_code_from++, output_code++)
  147.   {
  148.     set_mapped(p_table, input_code_from);
  149.     p_table->mapping[input_code_from] = output_code;
  150.   }
  151.   return 0;
  152. }
  153.  
  154. /*!------------------------------------------------------------------------
  155.  * \fn     as_chartrans_table_unset_mult(as_chartrans_table_t *p_table, unsigned input_code_from, unsigned input_code_to)
  156.  * \brief  invalidate translation entry block
  157.  * \param  p_table table to update
  158.  * \param  input_code_from new source start value
  159.  * \param  input_code_to new source end value (inclusive)
  160.  * \return 0 if success
  161.  * ------------------------------------------------------------------------ */
  162.  
  163. int as_chartrans_table_unset_mult(as_chartrans_table_t *p_table, unsigned input_code_from, unsigned input_code_to)
  164. {
  165.   if (input_code_from > input_code_to)
  166.     return EBADF;
  167.   if ((input_code_from > 255) || (input_code_to > 255))
  168.     return E2BIG;
  169.   for (; input_code_from <= input_code_to; input_code_from++)
  170.   {
  171.     clr_mapped(p_table, input_code_from);
  172.     p_table->mapping[input_code_from] = 0;
  173.   }
  174.   return 0;
  175. }
  176.  
  177. /*!------------------------------------------------------------------------
  178.  * \fn     as_chartrans_table_print(const as_chartrans_table_t *p_table, FILE *p_file)
  179.  * \brief  print table contents
  180.  * \param  p_table table to print
  181.  * \param  p_file where to print
  182.  * ------------------------------------------------------------------------ */
  183.  
  184. void as_chartrans_table_print(const as_chartrans_table_t *p_table, FILE *p_file)
  185. {
  186.   int z, z2, code;
  187.  
  188.   for (z = 0; z < 16; z++)
  189.   {
  190.     for (z2 = 0; z2 < 16; z2++)
  191.     {
  192.       code = z * 16 + z2;
  193.       if (is_mapped(p_table, code))
  194.         fprintf(p_file, " %02x", p_table->mapping[code]);
  195.       else
  196.         fprintf(p_file, " --");
  197.     }
  198.     fprintf(p_file, "  ");
  199.     for (z2 = 0; z2 < 16; z2++)
  200.     {
  201.       code = z * 16 + z2;
  202.       if (is_mapped(p_table, code))
  203.         fputc(p_table->mapping[code] > ' ' ? p_table->mapping[code] : '.', p_file);
  204.       else
  205.         fputc(' ', p_file);
  206.     }
  207.     fputc('\n', p_file);
  208.   }
  209. }
  210.  
  211. /*!------------------------------------------------------------------------
  212.  * \fn     as_chartrans_xlate(const as_chartrans_table_t *p_table, unsigned src)
  213.  * \brief  translate single character
  214.  * \param  p_table translation table to use
  215.  * \param  src character to translate
  216.  * \return translated character or -1
  217.  * ------------------------------------------------------------------------ */
  218.  
  219. int as_chartrans_xlate(const as_chartrans_table_t *p_table, unsigned src)
  220. {
  221.   return ((src <= 255) && is_mapped(p_table, src)) ? p_table->mapping[src] : -1;
  222. }
  223.  
  224. /*!------------------------------------------------------------------------
  225.  * \fn     as_chartrans_xlate_rev(const as_chartrans_table_t *p_table, unsigned src)
  226.  * \brief  untranslate single character
  227.  * \param  p_table translation table to use
  228.  * \param  src character to untranslate
  229.  * \return untranslated character or -1
  230.  * ------------------------------------------------------------------------ */
  231.  
  232. int as_chartrans_xlate_rev(const as_chartrans_table_t *p_table, unsigned src)
  233. {
  234.   unsigned z;
  235.  
  236.   if (src > 255)
  237.     return -1;
  238.   for (z = 0; z < 256; z++)
  239.     if (is_mapped(p_table, z) && (p_table->mapping[z] == src))
  240.       return z;
  241.   return -1;
  242. }
  243.  
  244. /*!------------------------------------------------------------------------
  245.  * \fn     as_chartrans_xlate_next(const as_chartrans_table_t *p_table, unsigned *p_dest, const char **pp_src, size_t *p_src_len)
  246.  * \brief  translate single character in string
  247.  * \param  p_table translation table to use
  248.  * \param  p_dest p_dest where to write result
  249.  * \param  pp_src pp_src source string (will be incremented by consumed # of characters)
  250.  * \param  p_src_len remaining length of source string
  251.  * \return 0 if success
  252.  *         ENOMEN -> end of string
  253.  *         ENOENT -> unmappable character
  254.  * ------------------------------------------------------------------------ */
  255.  
  256. int as_chartrans_xlate_next(const as_chartrans_table_t *p_table, unsigned *p_dest, const char **pp_src, size_t *p_src_len)
  257. {
  258.   usint code;
  259.  
  260.   if (!*p_src_len)
  261.     return ENOMEM;
  262.   code = ((usint)(**pp_src)) & 0xff;
  263.   if (!is_mapped(p_table, code))
  264.     return ENOENT;
  265.   *p_dest = p_table->mapping[code];
  266.   (*pp_src)++; (*p_src_len)--;
  267.   return 0;
  268. }
  269.  
  270. /*!------------------------------------------------------------------------
  271.  * \fn     as_chartrans_xlate_nonz_dynstr(const as_chartrans_table_t *p_table, struct as_nonz_dynstr *p_str, const struct sStrComp *p_src_arg)
  272.  * \brief  translate complete string
  273.  * \param  p_table translation table to use
  274.  * \param  p_str string to translate
  275.  * \param  p_src_arg source argument in case error occurs
  276.  * \return 0 if success
  277.  * ------------------------------------------------------------------------ */
  278.  
  279. int as_chartrans_xlate_nonz_dynstr(const as_chartrans_table_t *p_table, struct as_nonz_dynstr *p_str, const struct sStrComp *p_src_arg)
  280. {
  281.   char *p_run, *p_end;
  282.  
  283.   for (p_run = p_str->p_str, p_end = p_run + p_str->len; p_run < p_end; p_run++)
  284.   {
  285.     usint code = ((usint)(*p_run)) & 0xff;
  286.     if (!is_mapped(p_table, code))
  287.     {
  288.       if (p_src_arg)
  289.         WrStrErrorPos(ErrNum_UnmappedChar, p_src_arg);
  290.       return ENOENT;
  291.     }
  292.     *p_run = p_table->mapping[code];
  293.   }
  294.   return 0;
  295. }
  296.