ischeme.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <assert.h>
  5. #include <faux/str.h>
  6. #include <faux/list.h>
  7. #include <klish/khelper.h>
  8. #include <klish/kplugin.h>
  9. #include <klish/kentry.h>
  10. #include <klish/kscheme.h>
  11. #include <klish/ischeme.h>
  12. #define TAG "SCHEME"
  13. bool_t ischeme_parse_nested(const ischeme_t *ischeme, kscheme_t *kscheme,
  14. faux_error_t *error)
  15. {
  16. bool_t retval = BOOL_TRUE;
  17. if (!kscheme || !ischeme) {
  18. faux_error_add(error, TAG": Internal error");
  19. return BOOL_FALSE;
  20. }
  21. // PLUGIN list
  22. if (ischeme->plugins) {
  23. iplugin_t **p_iplugin = NULL;
  24. for (p_iplugin = *ischeme->plugins; *p_iplugin; p_iplugin++) {
  25. kplugin_t *kplugin = NULL;
  26. iplugin_t *iplugin = *p_iplugin;
  27. kplugin = iplugin_load(iplugin, error);
  28. if (!kplugin) {
  29. retval = BOOL_FALSE; // Don't stop
  30. continue;
  31. }
  32. if (!kscheme_add_plugins(kscheme, kplugin)) {
  33. // Search for PLUGIN duplicates
  34. if (kscheme_find_plugin(kscheme,
  35. kplugin_name(kplugin))) {
  36. faux_error_sprintf(error,
  37. TAG": Can't add duplicate PLUGIN "
  38. "\"%s\"", kplugin_name(kplugin));
  39. } else {
  40. faux_error_sprintf(error,
  41. TAG": Can't add PLUGIN \"%s\"",
  42. kplugin_name(kplugin));
  43. }
  44. kplugin_free(kplugin);
  45. retval = BOOL_FALSE;
  46. }
  47. }
  48. }
  49. // ENTRY list
  50. // ENTRYs can be duplicate. Duplicated ENTRY will add nested
  51. // elements to existent ENTRY. Also it can overwrite ENTRY attributes.
  52. // So there is no special rule which attribute value will be "on top".
  53. // It's a random. Technically later ENTRYs will rewrite previous
  54. // values.
  55. if (ischeme->entrys) {
  56. ientry_t **p_ientry = NULL;
  57. for (p_ientry = *ischeme->entrys; *p_ientry; p_ientry++) {
  58. kentry_t *nkentry = NULL;
  59. ientry_t *nientry = *p_ientry;
  60. const char *entry_name = nientry->name;
  61. if (entry_name)
  62. nkentry = kscheme_find_entry(kscheme, entry_name);
  63. // ENTRY already exists
  64. if (nkentry) {
  65. if (!ientry_parse(nientry, nkentry, error)) {
  66. retval = BOOL_FALSE;
  67. continue;
  68. }
  69. if (!ientry_parse_nested(nientry, nkentry,
  70. error)) {
  71. retval = BOOL_FALSE;
  72. continue;
  73. }
  74. continue;
  75. }
  76. // New ENTRY
  77. nkentry = ientry_load(nientry, error);
  78. if (!nkentry) {
  79. retval = BOOL_FALSE;
  80. continue;
  81. }
  82. kentry_set_parent(nkentry, NULL); // Set empty parent entry
  83. if (!kscheme_add_entrys(kscheme, nkentry)) {
  84. faux_error_sprintf(error,
  85. TAG": Can't add ENTRY \"%s\"",
  86. kentry_name(nkentry));
  87. kentry_free(nkentry);
  88. retval = BOOL_FALSE;
  89. continue;
  90. }
  91. }
  92. }
  93. if (!retval)
  94. faux_error_sprintf(error, TAG": Illegal nested elements");
  95. return retval;
  96. }
  97. bool_t ischeme_load(const ischeme_t *ischeme, kscheme_t *kscheme,
  98. faux_error_t *error)
  99. {
  100. assert(kscheme);
  101. if (!kscheme) {
  102. faux_error_sprintf(error, TAG": Internal error");
  103. return BOOL_FALSE;
  104. }
  105. // Parse nested elements
  106. return ischeme_parse_nested(ischeme, kscheme, error);
  107. }
  108. char *ischeme_deploy(const kscheme_t *scheme, int level)
  109. {
  110. char *str = NULL;
  111. char *tmp = NULL;
  112. kscheme_plugins_node_t *plugins_iter = NULL;
  113. kscheme_entrys_node_t *entrys_iter = NULL;
  114. tmp = faux_str_sprintf("ischeme_t sch = {\n");
  115. faux_str_cat(&str, tmp);
  116. faux_str_free(tmp);
  117. // PLUGIN list
  118. plugins_iter = kscheme_plugins_iter(scheme);
  119. if (plugins_iter) {
  120. kplugin_t *plugin = NULL;
  121. tmp = faux_str_sprintf("\n%*cPLUGIN_LIST\n\n", level, ' ');
  122. faux_str_cat(&str, tmp);
  123. faux_str_free(tmp);
  124. while ((plugin = kscheme_plugins_each(&plugins_iter))) {
  125. tmp = iplugin_deploy(plugin, level + 2);
  126. faux_str_cat(&str, tmp);
  127. faux_str_free(tmp);
  128. }
  129. tmp = faux_str_sprintf("%*cEND_PLUGIN_LIST,\n", level + 1, ' ');
  130. faux_str_cat(&str, tmp);
  131. faux_str_free(tmp);
  132. }
  133. // ENTRY list
  134. entrys_iter = kscheme_entrys_iter(scheme);
  135. if (entrys_iter) {
  136. kentry_t *entry = NULL;
  137. tmp = faux_str_sprintf("\n%*cENTRY_LIST\n\n", level, ' ');
  138. faux_str_cat(&str, tmp);
  139. faux_str_free(tmp);
  140. while ((entry = kscheme_entrys_each(&entrys_iter))) {
  141. tmp = ientry_deploy(entry, level + 2);
  142. faux_str_cat(&str, tmp);
  143. faux_str_free(tmp);
  144. }
  145. tmp = faux_str_sprintf("%*cEND_ENTRY_LIST,\n", level + 1, ' ');
  146. faux_str_cat(&str, tmp);
  147. faux_str_free(tmp);
  148. }
  149. tmp = faux_str_sprintf("};\n");
  150. faux_str_cat(&str, tmp);
  151. faux_str_free(tmp);
  152. return str;
  153. }