tbistring.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * tbistring.c
  3. *
  4. * Copyright (C) 2001, 2002, 2003, 2005, 2007, 2012 Imagination Technologies.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it under
  7. * the terms of the GNU General Public License version 2 as published by the
  8. * Free Software Foundation.
  9. *
  10. * String table functions provided as part of the thread binary interface for
  11. * Meta processors
  12. */
  13. #include <linux/export.h>
  14. #include <linux/string.h>
  15. #include <asm/tbx.h>
  16. /*
  17. * There are not any functions to modify the string table currently, if these
  18. * are required at some later point I suggest having a seperate module and
  19. * ensuring that creating new entries does not interfere with reading old
  20. * entries in any way.
  21. */
  22. const TBISTR *__TBIFindStr(const TBISTR *start,
  23. const char *str, int match_len)
  24. {
  25. const TBISTR *search = start;
  26. bool exact = true;
  27. const TBISEG *seg;
  28. if (match_len < 0) {
  29. /* Make match_len always positive for the inner loop */
  30. match_len = -match_len;
  31. exact = false;
  32. } else {
  33. /*
  34. * Also support historic behaviour, which expected match_len to
  35. * include null terminator
  36. */
  37. if (match_len && str[match_len-1] == '\0')
  38. match_len--;
  39. }
  40. if (!search) {
  41. /* Find global string table segment */
  42. seg = __TBIFindSeg(NULL, TBID_SEG(TBID_THREAD_GLOBAL,
  43. TBID_SEGSCOPE_GLOBAL,
  44. TBID_SEGTYPE_STRING));
  45. if (!seg || seg->Bytes < sizeof(TBISTR))
  46. /* No string table! */
  47. return NULL;
  48. /* Start of string table */
  49. search = seg->pGAddr;
  50. }
  51. for (;;) {
  52. while (!search->Tag)
  53. /* Allow simple gaps which are just zero initialised */
  54. search = (const TBISTR *)((const char *)search + 8);
  55. if (search->Tag == METAG_TBI_STRE) {
  56. /* Reached the end of the table */
  57. search = NULL;
  58. break;
  59. }
  60. if ((search->Len >= match_len) &&
  61. (!exact || (search->Len == match_len + 1)) &&
  62. (search->Tag != METAG_TBI_STRG)) {
  63. /* Worth searching */
  64. if (!strncmp(str, (const char *)search->String,
  65. match_len))
  66. break;
  67. }
  68. /* Next entry */
  69. search = (const TBISTR *)((const char *)search + search->Bytes);
  70. }
  71. return search;
  72. }
  73. const void *__TBITransStr(const char *str, int len)
  74. {
  75. const TBISTR *search = NULL;
  76. const void *res = NULL;
  77. for (;;) {
  78. /* Search onwards */
  79. search = __TBIFindStr(search, str, len);
  80. /* No translation returns NULL */
  81. if (!search)
  82. break;
  83. /* Skip matching entries with no translation data */
  84. if (search->TransLen != METAG_TBI_STRX) {
  85. /* Calculate base of translation string */
  86. res = (const char *)search->String +
  87. ((search->Len + 7) & ~7);
  88. break;
  89. }
  90. /* Next entry */
  91. search = (const TBISTR *)((const char *)search + search->Bytes);
  92. }
  93. /* Return base address of translation data or NULL */
  94. return res;
  95. }
  96. EXPORT_SYMBOL(__TBITransStr);