ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

255 lines
4.4 KiB

  1. #include "global_config.h"
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #include <stdlib.h>
  5. namespace cppcms {
  6. bool cppcms_config::get_tocken(FILE *f,tocken_t &T)
  7. {
  8. int c;
  9. while((c=fgetc(f))!=EOF) {
  10. if(c=='.') {
  11. T.first='.';
  12. return true;
  13. }
  14. else if(c=='{') {
  15. T.first='{';
  16. return true;
  17. }
  18. else if(c=='}') {
  19. T.first='}';
  20. return true;
  21. }
  22. else if(c=='=') {
  23. T.first='=';
  24. return true;
  25. }
  26. else if(c=='\n') {
  27. line_counter++;
  28. continue;
  29. }
  30. else if(c==' ' || c=='\r' || c=='\t') {
  31. continue;
  32. }
  33. else if(isalpha(c)) {
  34. T.second="";
  35. T.second.reserve(32);
  36. T.second+=(char)c;
  37. while((c=fgetc(f))!=EOF && (isalnum(c) || c=='_')) {
  38. T.second+=(char)c;
  39. }
  40. if(c!=EOF){
  41. ungetc(c,f);
  42. }
  43. T.first=WORD;
  44. return true;
  45. }
  46. else if(isdigit(c) || c=='-') {
  47. T.second="";
  48. T.second.reserve(32);
  49. T.second+=(char)c;
  50. T.first=INT;
  51. while((c=fgetc(f))!=EOF && isdigit(c)) {
  52. T.second+=(char)c;
  53. }
  54. if(c=='.') {
  55. T.second+='.';
  56. T.first=DOUBLE;
  57. while((c=fgetc(f))!=EOF && isdigit(c)) {
  58. T.second+=(char)c;
  59. }
  60. }
  61. if(T.second=="-" || T.second=="." || T.second=="-.") {
  62. throw cppcms_error("Illegal charrecters");
  63. }
  64. if(c!=EOF) {
  65. ungetc(c,f);
  66. }
  67. return true;
  68. }
  69. else if(c=='\"') {
  70. T.first=STR;
  71. T.second="";
  72. T.second.reserve(128);
  73. for(;;){
  74. c=fgetc(f);
  75. if(c=='\\'){
  76. if((c=fgetc(f))=='\"' ) {
  77. T.second+='"';
  78. continue;
  79. }
  80. else {
  81. T.second+='\\';
  82. }
  83. }
  84. if(c==EOF){
  85. throw cppcms_error("Unexpected EOF ");
  86. }
  87. if(c=='\n') line_counter++;
  88. if(c=='\"') {
  89. return true;
  90. }
  91. T.second+=(char)c;
  92. }
  93. }
  94. else if(c=='#' || c==';'){
  95. while((c=fgetc(f))!=EOF) {
  96. if(c=='\n'){
  97. line_counter++;
  98. break;
  99. }
  100. }
  101. if(c==EOF) {
  102. return false;
  103. }
  104. }
  105. else {
  106. throw cppcms_error(string("Unexpected charrecter")+(char)c);
  107. }
  108. }
  109. return false;
  110. }
  111. void cppcms_config::load(char const *fname)
  112. {
  113. if(loaded){
  114. return;
  115. }
  116. FILE *f=fopen(fname,"r");
  117. line_counter=1;
  118. if(!f) {
  119. throw cppcms_error(string("Failed to open file:")+fname);
  120. }
  121. tocken_t T;
  122. string key;
  123. int state=0;
  124. try{
  125. while(get_tocken(f,T) && state != -1) {
  126. switch(state) {
  127. case 0: if(T.first != WORD) {
  128. state=-1;
  129. }else{
  130. key=T.second;
  131. state=1;
  132. }
  133. break;
  134. case 1: if(T.first != '.')
  135. state=-1;
  136. else
  137. state=2;
  138. break;
  139. case 2: if(T.first!=WORD){
  140. state=-1;
  141. }else{
  142. state=3;
  143. key+='.';
  144. key+=T.second;
  145. }
  146. break;
  147. case 3: if(T.first!= '=')
  148. state=-1;
  149. else
  150. state=4;
  151. break;
  152. case 4: if(T.first=='{') {
  153. state=5;
  154. break;
  155. }
  156. if(T.first==INT) {
  157. long val=atol(T.second.c_str());
  158. data[key]=val;
  159. }
  160. else if(T.first==DOUBLE) {
  161. double val=atof(T.second.c_str());
  162. data[key]=val;
  163. }
  164. else if(T.first==STR){
  165. data[key]=T.second;
  166. }
  167. else {
  168. state=-1;
  169. break;
  170. }
  171. state=0;
  172. break;
  173. case 5:
  174. if(T.first==INT || T.first==DOUBLE || T.first==STR) {
  175. int fp=T.first;
  176. vector<long> vl;
  177. vector<double> vd;
  178. vector<string> vs;
  179. do {
  180. if(T.first=='}') {
  181. state=0;
  182. }
  183. else if(T.first==fp){
  184. switch(T.first) {
  185. case INT: vl.push_back(atol(T.second.c_str())); break;
  186. case DOUBLE: vd.push_back(atof(T.second.c_str())); break;
  187. case STR: vs.push_back(T.second); break;
  188. }
  189. }
  190. else {
  191. state=-1;
  192. }
  193. }while(state==5 && get_tocken(f,T));
  194. if(state==0) {
  195. switch(fp) {
  196. case INT: data[key]=vl; break;
  197. case DOUBLE: data[key]=vd; break;
  198. case STR: data[key]=vs; break;
  199. };
  200. }
  201. }
  202. else
  203. state=-1;
  204. break;
  205. }
  206. }
  207. if(state!=0) {
  208. throw cppcms_error("Parsing error");
  209. }
  210. }
  211. catch (cppcms_error &err){
  212. fclose(f);
  213. char stmp[32];
  214. snprintf(stmp,32," at line %d",line_counter);
  215. throw cppcms_error(string(err.what())+stmp);
  216. }
  217. fclose(f);
  218. loaded=true;
  219. }
  220. void cppcms_config::load(int argc,char *argv[],char const *def)
  221. {
  222. if(loaded) {
  223. return;
  224. }
  225. char const *def_file=def;
  226. int i;
  227. for(i=1;i<argc;i++) {
  228. if(strncmp(argv[i],"--config=",9)==0) {
  229. def_file=argv[i]+9;
  230. break;
  231. }
  232. else if(strcmp(argv[i],"-c")==0 && i+1<argc) {
  233. def_file=argv[i+1];
  234. break;
  235. }
  236. }
  237. if(def_file==NULL) {
  238. def_file=getenv("CPPCMS_CONFIG");
  239. }
  240. if(def_file==NULL) {
  241. throw cppcms_error("Configuration file not defined");
  242. }
  243. load(def_file);
  244. }
  245. }