Add multiple temps to panel watchscreen if there are more than two enabled, top line...
[clinton/Smoothieware.git] / src / libs / ConfigSources / FileConfigSource.cpp
CommitLineData
7b49793d 1/*
c295905f
AW
2 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
3 Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
4 Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
7b49793d 5 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
c295905f
AW
6*/
7
8#include "libs/Kernel.h"
9#include "ConfigValue.h"
10#include "FileConfigSource.h"
11#include "ConfigCache.h"
f45e6161 12#include "checksumm.h"
61134a65 13#include "utils.h"
a39e1557
AW
14#include <malloc.h>
15
c295905f
AW
16using namespace std;
17#include <string>
bcb96295 18#include <string.h>
c295905f 19
f45e6161
L
20#define include_checksum CHECKSUM("include")
21
577414f6
JM
22FileConfigSource::FileConfigSource(string config_file, const char *name)
23{
24 this->name_checksum = get_checksum(name);
8d857d2e 25 this->config_file = config_file;
c295905f
AW
26 this->config_file_found = false;
27}
28
2ee2ad19 29bool FileConfigSource::readLine(string& line, int lineno, FILE *fp)
bcb96295
JM
30{
31 char buf[132];
32 char *l= fgets(buf, sizeof(buf)-1, fp);
33 if(l != NULL) {
34 if(buf[strlen(l)-1] != '\n') {
35 // truncate long lines
2ee2ad19
JM
36 if(lineno != 0) {
37 // report if it is not truncating a comment
38 if(strchr(buf, '#') == NULL)
39 printf("Truncated long line %d in: %s\n", lineno, config_file.c_str());
40 }
bcb96295
JM
41 // read until the next \n or eof
42 int c;
43 while((c=fgetc(fp)) != '\n' && c != EOF) /* discard */;
44 }
45 line.assign(buf);
46 return true;
47 }
48
49 return false;
50}
51
c295905f 52// Transfer all values found in the file to the passed cache
577414f6
JM
53void FileConfigSource::transfer_values_to_cache( ConfigCache *cache )
54{
577414f6
JM
55 if( !this->has_config_file() ) {
56 return;
57 }
f45e6161
L
58 transfer_values_to_cache( cache, this->get_config_file().c_str());
59}
60
61void FileConfigSource::transfer_values_to_cache( ConfigCache *cache, const char * file_name )
62{
63 if( !file_exists(file_name) ) {
64 return;
65 }
66
7b49793d 67 // Open the config file ( find it if we haven't already found it )
f45e6161 68 FILE *lp = fopen(file_name, "r");
bcb96295 69
2ee2ad19 70 int ln= 1;
7b49793d 71 // For each line
bcb96295
JM
72 while(!feof(lp)) {
73 string line;
2ee2ad19 74 if(readLine(line, ln++, lp)) {
f45e6161
L
75 // process the config line and store the value in cache
76 ConfigValue* cv = process_line_from_ascii_config(line, cache);
77
78 // if this line is an include directive then attempt to read the included file
79 if(cv->check_sums[0] == include_checksum) {
80 string inc_file_name = cv->value.c_str();
81 if(!file_exists(inc_file_name)) {
82 // if the file is not found at the location entered then look around for it a bit
83 if(inc_file_name[0] != '/') inc_file_name = "/" + inc_file_name;
84 string path(file_name);
85 path = path.substr(0,path.find_last_of('/'));
86
87 // first check the path of the current config file
88 if(file_exists(path + inc_file_name)) inc_file_name = path + inc_file_name;
89 // then check root locations
90 else if(file_exists("/sd" + inc_file_name)) inc_file_name = "/sd" + inc_file_name;
91 else if(file_exists("/local" + inc_file_name)) inc_file_name = "/local" + inc_file_name;
92 }
93 if(file_exists(inc_file_name)) {
c77d6dae
JM
94 printf("Including config file: %s\n", inc_file_name.c_str());
95
f45e6161
L
96 // save position in current config file
97 fpos_t pos;
98 fgetpos(lp, &pos);
99
100 // open and read the included file
101 freopen(inc_file_name.c_str(), "r", lp);
102 this->transfer_values_to_cache(cache, inc_file_name.c_str());
103
104 // reopen the current config file and restore position
105 freopen(file_name, "r", lp);
106 fsetpos(lp, &pos);
c77d6dae
JM
107 }else{
108 printf("Unable to find included config file: %s\n", inc_file_name.c_str());
f45e6161
L
109 }
110 }
bcb96295 111 }else break;
577414f6 112 }
bcb96295 113 fclose(lp);
c295905f
AW
114}
115
5913c006 116// Return true if the check_sums match
577414f6
JM
117bool FileConfigSource::is_named( uint16_t check_sum )
118{
5efaa1b1
L
119 return check_sum == this->name_checksum;
120}
121
d8cff5af
JM
122// OverWrite or append a config setting to the file
123bool FileConfigSource::write( string setting, string value )
577414f6 124{
d8cff5af
JM
125 if( !this->has_config_file() ) {
126 return false;
127 }
128
129 uint16_t setting_checksums[3];
130 get_checksums(setting_checksums, setting );
131
5913c006
L
132 // Open the config file ( find it if we haven't already found it )
133 FILE *lp = fopen(this->get_config_file().c_str(), "r+");
d8cff5af
JM
134
135 // search each line for a match
136 while(!feof(lp)) {
137 string line;
138 fpos_t bol, eol;
139 fgetpos( lp, &bol ); // get start of line
2ee2ad19 140 if(readLine(line, 0, lp)) {
d8cff5af
JM
141 fgetpos( lp, &eol ); // get end of line
142 if(!process_line_from_ascii_config(line, setting_checksums).empty()) {
143 // found it
144 unsigned int free_space = eol - bol - 4; // length of line
145 // check we have enough space for this insertion
146 if( (setting.length() + value.length() + 3) > free_space ) {
147 //THEKERNEL->streams->printf("ERROR: Not enough room for value\r\n");
148 fclose(lp);
149 return false;
150 }
151
152 // Update line, leaves whatever was at end of line there just overwrites the key and value
153 fseek(lp, bol, SEEK_SET);
154 fputs(setting.c_str(), lp);
155 fputs(" ", lp);
156 fputs(value.c_str(), lp);
157 fputs(" #", lp);
5913c006 158 fclose(lp);
d8cff5af 159 return true;
5913c006 160 }
d8cff5af
JM
161 }else break;
162 }
163
164 // not found so append the new value
5913c006 165 fclose(lp);
d8cff5af
JM
166 lp = fopen(this->get_config_file().c_str(), "a");
167 fputs("\n", lp);
168 fputs(setting.c_str(), lp);
169 fputs(" ", lp);
170 fputs(value.c_str(), lp);
171 fputs(" # added\n", lp);
172 fclose(lp);
173
174 return true;
5913c006 175}
5efaa1b1 176
5761c645 177// Return the value for a specific checksum
577414f6
JM
178string FileConfigSource::read( uint16_t check_sums[3] )
179{
5761c645
L
180 string value = "";
181
577414f6
JM
182 if( this->has_config_file() == false ) {
183 return value;
184 }
185
7b49793d 186 // Open the config file ( find it if we haven't already found it )
bcb96295 187 FILE *lp = fopen(this->get_config_file().c_str(), "r");
7b49793d 188 // For each line
bcb96295
JM
189 while(!feof(lp)) {
190 string line;
2ee2ad19 191 if(readLine(line, 0, lp)) {
bcb96295
JM
192 value = process_line_from_ascii_config(line, check_sums);
193 if(!value.empty()) break; // found it
194 }else break;
577414f6 195 }
bcb96295 196 fclose(lp);
5761c645
L
197
198 return value;
199}
5efaa1b1 200
c295905f 201// Return wether or not we have a readable config file
577414f6
JM
202bool FileConfigSource::has_config_file()
203{
204 if( this->config_file_found ) {
205 return true;
206 }
8d857d2e 207 this->try_config_file(this->config_file);
577414f6 208 if( this->config_file_found ) {
c295905f 209 return true;
577414f6 210 } else {
c295905f
AW
211 return false;
212 }
213
214}
215
216// Tool function for get_config_file
577414f6
JM
217inline void FileConfigSource::try_config_file(string candidate)
218{
219 if(file_exists(candidate)) {
220 this->config_file_found = true;
221 }
c295905f
AW
222}
223
224// Get the filename for the config file
577414f6
JM
225string FileConfigSource::get_config_file()
226{
227 if( this->config_file_found ) {
228 return this->config_file;
229 }
230 if( this->has_config_file() ) {
c295905f 231 return this->config_file;
577414f6 232 } else {
c295905f 233 printf("ERROR: no config file found\r\n");
577414f6 234 return "";
c295905f
AW
235 }
236}
237
238
239
240
241
242