scanctx.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /* ----------------------------------------------------------------------------
  2. libconfig - A library for processing structured configuration files
  3. Copyright (C) 2005-2010 Mark A Lindner
  4. This file is part of libconfig.
  5. This library is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. This library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this library. If not, see <http://www.gnu.org/licenses/>.
  15. ----------------------------------------------------------------------------
  16. */
  17. #include "scanctx.h"
  18. #include "wincompat.h"
  19. #include <stddef.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #define STRING_BLOCK_SIZE 64
  23. #define CHUNK_SIZE 32
  24. /* ------------------------------------------------------------------------- */
  25. static const char *err_bad_include = "cannot open include file";
  26. static const char *err_include_too_deep = "include file nesting too deep";
  27. /* ------------------------------------------------------------------------- */
  28. static const char *__scanctx_add_filename(struct scan_context *ctx,
  29. const char *filename)
  30. {
  31. unsigned int count = ctx->num_filenames;
  32. const char **f;
  33. for(f = ctx->filenames; count > 0; ++f, --count)
  34. {
  35. if(!strcmp(*f, filename))
  36. {
  37. free((void *)filename);
  38. return(*f); /* already in list */
  39. }
  40. }
  41. if((ctx->num_filenames % CHUNK_SIZE) == 0)
  42. {
  43. ctx->filenames = (const char **)realloc(
  44. (void *)ctx->filenames,
  45. (ctx->num_filenames + CHUNK_SIZE) * sizeof(const char *));
  46. }
  47. ctx->filenames[ctx->num_filenames] = filename;
  48. ++ctx->num_filenames;
  49. return(filename);
  50. }
  51. /* ------------------------------------------------------------------------- */
  52. void scanctx_init(struct scan_context *ctx, const char *top_filename)
  53. {
  54. memset(ctx, 0, sizeof(struct scan_context));
  55. if(top_filename)
  56. ctx->top_filename = __scanctx_add_filename(ctx, strdup(top_filename));
  57. }
  58. /* ------------------------------------------------------------------------- */
  59. const char **scanctx_cleanup(struct scan_context *ctx,
  60. unsigned int *num_filenames)
  61. {
  62. int i;
  63. for(i = 0; i < ctx->depth; ++i)
  64. fclose(ctx->streams[i]);
  65. free((void *)(strbuf_release(&(ctx->string))));
  66. *num_filenames = ctx->num_filenames;
  67. return(ctx->filenames);
  68. }
  69. /* ------------------------------------------------------------------------- */
  70. FILE *scanctx_push_include(struct scan_context *ctx, void *buffer,
  71. const char **error)
  72. {
  73. FILE *fp = NULL;
  74. const char *file;
  75. char *full_file = NULL;
  76. *error = NULL;
  77. if(ctx->depth == MAX_INCLUDE_DEPTH)
  78. {
  79. *error = err_include_too_deep;
  80. return(NULL);
  81. }
  82. file = scanctx_take_string(ctx);
  83. if(ctx->config->include_dir)
  84. {
  85. full_file = (char *)malloc(strlen(ctx->config->include_dir) + strlen(file)
  86. + 2);
  87. strcpy(full_file, ctx->config->include_dir);
  88. strcat(full_file, FILE_SEPARATOR);
  89. strcat(full_file, file);
  90. }
  91. fp = fopen(full_file ? full_file : file, "rt");
  92. free((void *)full_file);
  93. if(fp)
  94. {
  95. ctx->streams[ctx->depth] = fp;
  96. ctx->files[ctx->depth] = __scanctx_add_filename(ctx, file);
  97. ctx->buffers[ctx->depth] = buffer;
  98. ++(ctx->depth);
  99. }
  100. else
  101. {
  102. free((void *)file);
  103. *error = err_bad_include;
  104. }
  105. return(fp);
  106. }
  107. /* ------------------------------------------------------------------------- */
  108. void *scanctx_pop_include(struct scan_context *ctx)
  109. {
  110. void *buffer;
  111. if(ctx->depth == 0)
  112. return(NULL); /* stack underflow */
  113. --(ctx->depth);
  114. buffer = ctx->buffers[ctx->depth];
  115. fclose(ctx->streams[ctx->depth]);
  116. return(buffer);
  117. }
  118. /* ------------------------------------------------------------------------- */
  119. char *scanctx_take_string(struct scan_context *ctx)
  120. {
  121. char *r = strbuf_release(&(ctx->string));
  122. return(r ? r : strdup(""));
  123. }
  124. /* ------------------------------------------------------------------------- */
  125. const char *scanctx_current_filename(struct scan_context *ctx)
  126. {
  127. return((ctx->depth == 0) ? ctx->top_filename : ctx->files[ctx->depth - 1]);
  128. }
  129. /* ------------------------------------------------------------------------- */
  130. /* eof */