1 // ----------------------------------------------------------------------------
2 // rigxml.cxx - parse a rig control xml file
3 //
4 // Copyright (C) 2007-2009
5 //		Dave Freese, W1HKJ
6 //
7 // This file is part of fldigi.
8 //
9 // Fldigi is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 3 of the License, or
12 // (at your option) any later version.
13 //
14 // Fldigi is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with fldigi.  If not, see <http://www.gnu.org/licenses/>.
21 // ----------------------------------------------------------------------------
22 
23 #include <config.h>
24 
25 #include <fstream>
26 #include <string>
27 #include <list>
28 
29 #include <FL/filename.H>
30 
31 #include "gettext.h"
32 #include "rigio.h"
33 #include "rigxml.h"
34 #include "rigsupport.h"
35 #ifdef RIGCATTEST
36 	#include "rigCAT.h"
37 #else
38 	#include "main.h"
39 #endif
40 #include "debug.h"
41 
42 #include "configuration.h"
43 #include "fileselect.h"
44 #include "confdialog.h"
45 
46 #include "icons.h"
47 #include "fl_digi.h"
48 
49 using namespace std;
50 
51 //#define DEBUGXML 1
52 
53 void parseRIGDEF(size_t &);
54 void parseRIG(size_t &);
55 void parseCOMMAND(size_t &);
56 void parseREPLY(size_t &);
57 void parseMODES(size_t &);
58 void parseBANDWIDTHS(size_t &);
59 void parseBWCMD(size_t &);
60 void parseBWREPLY(size_t &);
61 void parseMODECMD(size_t &);
62 void parseMODEREPLY(size_t &);
63 void parseTITLE(size_t &);
64 void parseLSBMODES(size_t &);
65 void parseDISCARD(size_t &);
66 void parseDEBUG(size_t &);
67 void parseNOSERIAL(size_t &);
68 void parseASCII(size_t &);
69 
70 void parseWRITE_DELAY(size_t &);
71 void parseINIT_DELAY(size_t &);
72 void parseWAIT_FOR_DEVICE(size_t &);
73 void parsePOST_WRITE_DELAY(size_t &);
74 void parseRETRIES(size_t &);
75 void parseTIMEOUT(size_t &);
76 void parseBAUDRATE(size_t &);
77 void parseSTOPBITS(size_t &);
78 void parseRTSCTS(size_t &);
79 void parseCMDPTT(size_t &);
80 void parseRTSPLUS(size_t &);
81 void parseDTRPLUS(size_t &);
82 void parseRTSPTT(size_t &);
83 void parseDTRPTT(size_t &);
84 void parseRESTORE_TIO(size_t &);
85 void parseECHO(size_t &);
86 void parseVSP(size_t &);
87 void parseLOGSTR(size_t &);
88 void parsePOLLINT(size_t &);
89 void parseSMETER(size_t &);
90 void parsePMETER(size_t &);
91 void parseNOTCH(size_t &);
92 void parsePWRLEVEL(size_t &);
93 
94 void parseIOSsymbol(size_t &);
95 void parseIOSsize(size_t &);
96 void parseIOSbytes(size_t &);
97 void parseIOSbyte(size_t &);
98 void parseIOSdata(size_t &);
99 void parseIOSinfo(size_t &);
100 void parseIOSok(size_t &);
101 void parseIOSbad(size_t &);
102 void parseIOSstring(size_t &);
103 void parseIOSint(size_t &);
104 void parseIOSfill(size_t &);
105 
106 void parseDTYPE(size_t &);
107 void parseDSIZE(size_t &);
108 void parseDMAX(size_t &);
109 void parseDMIN(size_t &);
110 void parseDRESOL(size_t &);
111 void parseDREV(size_t &);
112 void parseDMAKS(size_t &);
113 void parseDSHIFT(size_t &);
114 
115 void print(size_t &);
116 
117 list<XMLIOS>	commands;
118 list<XMLIOS>	reply;
119 list<MODE> 		lmodes;
120 list<BW> 		lbws;
121 list<BW>		lbwCMD;
122 list<BW>		lbwREPLY;
123 list<MODE>		lmodeCMD;
124 list<MODE>		lmodeREPLY;
125 list<string> 	LSBmodes;
126 
127 XMLRIG xmlrig;
128 
129 XMLIOS iosTemp;
130 
131 string strXML;
132 
133 TAGS rigdeftags[] = {
134 	{"<RIGDEF",		parseRIGDEF},
135 	{"<RIG", 		parseRIG},
136 	{"<COMMAND",	parseCOMMAND},
137 	{"<REPLY",		parseREPLY},
138 	{"<BANDWIDTHS", parseBANDWIDTHS},
139 	{"<BW-CMD",		parseBWCMD},
140 	{"<BW-REPLY",	parseBWREPLY},
141 	{"<MODES",		parseMODES},
142 	{"<MODE-CMD",	parseMODECMD},
143 	{"<MODE-REPLY", parseMODEREPLY},
144 	{"<TITLE",		parseTITLE},
145 	{"<LSBMODES",	parseLSBMODES},
146 	{"<PROGRAMMER", parseDISCARD},
147 	{"<STATUS",		parseDISCARD},
148 	{"<WRITE_DELAY", parseWRITE_DELAY},
149 	{"<INIT_DELAY", parseINIT_DELAY},
150 	{"<POST_WRITE_DELAY", parsePOST_WRITE_DELAY},
151 	{"<RETRIES", parseRETRIES},
152 	{"<TIMEOUT", parseTIMEOUT},
153 	{"<BAUDRATE", parseBAUDRATE},
154 	{"<RTSCTS", parseRTSCTS},
155 	{"<RTSPLUS", parseRTSPLUS},
156 	{"<DTRPLUS", parseDTRPLUS},
157 	{"<RTSPTT", parseRTSPTT},
158 	{"<DTRPTT", parseDTRPTT},
159 	{"<WAIT_FOR_DEVICE", parseWAIT_FOR_DEVICE},
160 	{"<RESTORE_TIO", parseRESTORE_TIO},
161 	{"<ECHO", parseECHO},
162 	{"<CMDPTT", parseCMDPTT},
163 	{"<STOPBITS", parseSTOPBITS},
164 	{"<VSP", parseVSP},
165 	{"<LOGSTR", parseLOGSTR},
166 	{"<POLLINT", parsePOLLINT},
167 	{"<SMETER", parseSMETER},
168 	{"<PMETER", parsePMETER},
169 	{"<NOTCH", parseNOTCH},
170 	{"<PWRLEVEL", parsePWRLEVEL},
171 	{"<DEBUG", parseDEBUG},
172 	{"<NOSERIAL", parseNOSERIAL},
173 	{"<ASCII", parseASCII},
174 	{0, 0}
175 };
176 
177 TAGS commandtags[] = {
178 	{"<SIZE",	parseIOSsize},
179 	{"<SYMBOL",	parseIOSsymbol},
180 	{"<BYTES",	parseIOSbytes},
181 	{"<BYTE",	parseIOSbyte},
182 	{"<DATA",	parseIOSdata},
183 	{"<STRING", parseIOSstring},
184 	{"<INT", 	parseIOSint},
185 	{"<INFO",	parseIOSinfo},
186 	{"<OK",		parseIOSok},
187 	{"<BAD",	parseIOSbad},
188 	{0,0}
189 };
190 
191 TAGS replytags[] = {
192 	{"<SIZE",	parseIOSsize},
193 	{"<SYMBOL",	parseIOSsymbol},
194 	{"<BYTES",	parseIOSbytes},
195 	{"<BYTE",	parseIOSbyte},
196 	{"<DATA",	parseIOSdata},
197 	{"<STRING", parseIOSstring},
198 	{"<INT",	parseIOSint},
199 	{"<FILL",	parseIOSfill},
200 	{0,0}
201 };
202 
203 TAGS datatags[] = {
204 	{"<DTYPE",	parseDTYPE},
205 	{"<SIZE",	parseDSIZE},
206 	{"<MAX",	parseDMAX},
207 	{"<MIN",	parseDMIN},
208 	{"<RESOL",	parseDRESOL},
209 	{"<REV",	parseDREV},
210 	{"<MASK",	parseDMAKS},
211 	{"<SHIFT",	parseDSHIFT},
212 	{0,0}
213 }
214 ;
215 
216 //=====================================================================
217 
print(size_t & p0,int indent)218 void print(size_t &p0, int indent)
219 {
220 #ifdef DEBUGXML
221 	std::string istr(indent, '\t');
222 	size_t tend = strXML.find(">", p0);
223 	LOG_INFO("%s%s", istr.c_str(), strXML.substr(p0, tend - p0 + 1).c_str());
224 #endif
225 }
226 
tagEnd(size_t p0)227 size_t tagEnd(size_t p0)
228 {
229 	size_t p1, p2, p3;
230 	p1 = p0;
231 	string strtag = "</";
232 	p2 = strXML.find(">", p0);
233 	p3 = strXML.find(" ", p0);
234 	if (p2 == string::npos) {
235 		return p2;
236 	}
237 	if (p3 < p2)
238 		p2 = p3;
239 	strtag.append(strXML.substr(p1 + 1, p2 - p1 - 1));
240 	strtag.append(">");
241 	p3 = strXML.find(strtag, p1);
242 	return p3;
243 }
244 
nextTag(size_t p0)245 size_t nextTag(size_t p0)
246 {
247 	p0 = strXML.find("<", p0+1);
248 	return p0;
249 }
250 
getElement(size_t p0)251 string getElement(size_t p0)
252 {
253 	size_t p1 = strXML.find(">",p0),
254 		   p2 = nextTag(p1+1);
255 	if (p1 == string::npos || p2 == string::npos)
256 		return "";
257 	p1++; p2--;
258 	while (p1 < p2 && strXML[p1] == ' ') p1++; // skip leading spaces
259 	while (p1 < p2 && strXML[p2] == ' ') p2--; // skip trailing spaces
260 	return strXML.substr(p1, p2 - p1 + 1);
261 }
262 
getInt(size_t p0)263 int getInt(size_t p0)
264 {
265 	string stemp = getElement(p0);
266 	if (stemp.length() == 0)
267 		return 0;
268 	return atoi(stemp.c_str());
269 }
270 
getFloat(size_t p0)271 float getFloat(size_t p0)
272 {
273 	string stemp = getElement(p0);
274 	if (stemp.length() == 0)
275 		return 0;
276 	return atof(stemp.c_str());
277 }
278 
getBool(size_t p0)279 bool getBool( size_t p0)
280 {
281 	string stemp = getElement(p0);
282 	if (stemp.length() == 0)
283 		return false;
284 	if (strcasecmp(stemp.c_str(), "true") == 0)
285 		return true;
286 	if (stemp == "1") return true;
287 	return false;
288 }
289 
getByte(size_t p0)290 char getByte(size_t p0)
291 {
292 	unsigned int val;
293 	if (sscanf( getElement(p0).c_str(), "%x", &val ) != 1)
294 		return 0;
295 	return (val & 0xFF);
296 }
297 
getBytes(size_t p0)298 string getBytes(size_t p0)
299 {
300 	unsigned int val;
301 	size_t space;
302 	string stemp = getElement(p0);
303 	string s;
304 	while ( stemp.length() ) {
305 		if (sscanf( stemp.c_str(), "%x", &val) != 1) {
306 			s = "";
307 			return s;
308 		}
309 		s += (char)(val & 0xFF);
310 		space = stemp.find(" ");
311 		if (space == string::npos) break;
312 		stemp.erase(0, space + 1);
313 	}
314 	return s;
315 }
316 
isInt(size_t p0,int & i)317 bool isInt(size_t p0, int &i)
318 {
319 //	p0 = nextTag(p0);
320 	if (strXML.find("<INT", p0) != p0)
321 		return false;
322 	i = getInt(p0);
323 	return true;
324 }
325 
isByte(size_t p0,char & ch)326 bool isByte(size_t p0, char &ch)
327 {
328 //	p0 = nextTag(p0);
329 	if (strXML.find("<BYTE", p0) != p0)
330 		return false;
331 	ch = getByte(p0);
332 	return true;
333 }
334 
isBytes(size_t p0,string & s)335 bool isBytes( size_t p0, string &s )
336 {
337 //	p0 = nextTag(p0);
338 	if (strXML.find ("<BYTES", p0) != p0)
339 		return false;
340 	s = getBytes(p0);
341 	return true;
342 }
343 
isString(size_t p0,string & s)344 bool isString( size_t p0, string &s )
345 {
346 //	p0 = nextTag(p0);
347 	if (strXML.find("<STRING", p0) != p0)
348 		return false;
349 	s = getElement(p0);
350 	return true;
351 }
352 
isSymbol(size_t p0,string & s)353 bool isSymbol( size_t p0, string &s)
354 {
355 	if (strXML.find("<SYMBOL", p0) != p0)
356 		return false;
357 	s = getElement(p0);
358 	return true;
359 }
360 
tagIs(size_t & p0,string tag)361 bool tagIs(size_t &p0, string tag)
362 {
363 	return (strXML.find(tag,p0) == p0);
364 }
365 
366 //---------------------------------------------------------------------
367 // Parse modesTO definitions
368 //---------------------------------------------------------------------
369 
parseMODEdefs(size_t & p0,list<MODE> & lmd)370 void parseMODEdefs(size_t &p0, list<MODE> &lmd)
371 {
372 	size_t pend = tagEnd(p0);
373 	size_t elend;
374 	char ch;
375 	int n;
376 	string stemp;
377 	string strELEMENT;
378 	if (pend == string::npos) {
379 		p0++;
380 		return;
381 	}
382 	print(p0,0);
383 	p0 = nextTag(p0);
384 	while (p0 != string::npos && p0 < pend && tagIs(p0, "<ELEMENT")) {
385 		elend = tagEnd(p0);
386 		p0 = nextTag(p0);
387 		if (isSymbol(p0, strELEMENT)) {
388 			p0 = tagEnd(p0);
389 			p0 = nextTag(p0);
390 			while (p0 != string::npos && p0 < elend) {
391 				print(p0,1);
392 				if ( isBytes(p0, stemp) ) {
393 					lmd.push_back(MODE(strELEMENT,stemp));
394 				}
395 				else if ( isByte(p0, ch) ) {
396 					stemp = ch;
397 					lmd.push_back(MODE(strELEMENT,stemp));
398 				}
399 				else if ( isInt(p0, n) ) {
400 					stemp = (char)(n & 0xFF);
401 					lmd.push_back(MODE(strELEMENT, stemp));
402 				}
403 				else if ( isString(p0, stemp) ) {
404 					lmd.push_back(MODE(strELEMENT,stemp));
405 				}
406 				p0 = tagEnd(p0);
407 				p0 = nextTag(p0);
408 			}
409 		}
410 		p0 = nextTag(p0);
411 	}
412 	p0 = pend;
413 }
414 
parseMODES(size_t & p0)415 void parseMODES(size_t &p0)
416 {
417 	parseMODEdefs(p0, lmodes);
418 }
419 
420 
parseMODECMD(size_t & p0)421 void parseMODECMD(size_t &p0)
422 {
423 	parseMODEdefs(p0, lmodeCMD);
424 }
425 
parseMODEREPLY(size_t & p0)426 void parseMODEREPLY(size_t &p0)
427 {
428 	parseMODEdefs(p0, lmodeREPLY);
429 }
430 
parseLSBMODES(size_t & p0)431 void parseLSBMODES(size_t &p0)
432 {
433 	size_t pend = tagEnd(p0);
434 	string sMode;
435 	print(p0,0);
436 	p0 = nextTag(p0);
437 	while (p0 < pend && isString(p0, sMode)) {
438 		LSBmodes.push_back(sMode);
439 		print (p0,1);
440 		p0 = tagEnd(p0);
441 		p0 = nextTag(p0);
442 	}
443 	p0 = pend;
444 }
445 
446 //---------------------------------------------------------------------
447 // Parse Bandwidth definitions
448 //---------------------------------------------------------------------
449 
parseBWdefs(size_t & p0,list<BW> & lbw)450 void parseBWdefs(size_t &p0, list<BW> &lbw)
451 {
452 	size_t pend = tagEnd(p0);
453 	size_t elend;
454 	char ch;
455 	int n;
456 	string strELEMENT;
457 	string stemp;
458 	if (pend == string::npos) {
459 		LOG_ERROR("Unmatched tag %s", strXML.substr(p0, 10).c_str());
460 		p0++;
461 		return;
462 	}
463 	print(p0,0);
464 	size_t p1 = nextTag(p0);
465 	while (p1 != string::npos && p1 < pend && tagIs(p1, "<ELEMENT")) {
466 		elend = tagEnd(p1);
467 		if (elend == string::npos || elend > pend) {
468 			LOG_ERROR("Unmatched tag %s", "<ELEMENT");
469 			p0 = pend;
470 			return;
471 		}
472 		p1 = nextTag(p1);
473 		if (isSymbol(p1, strELEMENT)) {
474 			p1 = tagEnd(p1);
475 			p1 = nextTag(p1);
476 			while (p1 != string::npos && p1 < elend) {
477 				print(p1,1);
478 				if ( isBytes(p1, stemp) ) {
479 					lbw.push_back(BW(strELEMENT,stemp));
480 					p1 = tagEnd(p1);
481 				}
482 				else if ( isByte(p1, ch) ) {
483 					stemp = ch;
484 					lbw.push_back(BW(strELEMENT,stemp));
485 					p1 = tagEnd(p1);
486 				}
487 				else if ( isInt(p1, n) ) {
488 					stemp = (char)(n & 0xFF);
489 					lbw.push_back(BW(strELEMENT, stemp));
490 					p1 = tagEnd(p1);
491 				}
492 				else if ( isString(p1, stemp) ) {
493 					lbw.push_back(BW(strELEMENT,stemp));
494 					p1 = tagEnd(p1);
495 				} else {
496 					LOG_ERROR("Invalid tag: %s", strXML.substr(p1, 10).c_str());
497 					parseDISCARD(p1);
498 				}
499 				p1 = nextTag(p1);
500 			}
501 		}
502 		p1 = nextTag(p1);
503 	}
504 	p0 = pend;
505 }
506 
parseBANDWIDTHS(size_t & p0)507 void parseBANDWIDTHS(size_t &p0)
508 {
509 	parseBWdefs(p0, lbws);
510 }
511 
parseBWCMD(size_t & p0)512 void parseBWCMD(size_t &p0)
513 {
514 	parseBWdefs(p0, lbwCMD);
515 }
516 
parseBWREPLY(size_t & p0)517 void parseBWREPLY(size_t &p0)
518 {
519 	parseBWdefs(p0, lbwREPLY);
520 }
521 
522 //---------------------------------------------------------------------
523 // Parse Title definition
524 //---------------------------------------------------------------------
525 
parseTITLE(size_t & p0)526 void parseTITLE(size_t &p0)
527 {
528 	size_t pend = tagEnd(p0);
529 	xmlrig.rigTitle = getElement(p0);
530 	p0 = pend;
531 }
532 
533 //---------------------------------------------------------------------
534 // Parse Rig definition
535 //---------------------------------------------------------------------
536 
parseRIG(size_t & p0)537 void parseRIG(size_t &p0)
538 {
539 	size_t pend = tagEnd(p0);
540 	p0 = pend;
541 }
542 
543 //---------------------------------------------------------------------
544 // Parse DEBUG, use during xml file creation/testing
545 //---------------------------------------------------------------------
546 
parseDEBUG(size_t & p0)547 void parseDEBUG(size_t &p0){
548 	bool val = getBool(p0);
549 	xmlrig.debug = val;
550 	size_t pend = tagEnd(p0);
551 	p0 = pend;
552 }
553 
554 //---------------------------------------------------------------------
555 // Parse NOSERIAL, use during xml file creation/testing
556 // suppresses serial port i/o
557 //---------------------------------------------------------------------
558 
parseNOSERIAL(size_t & p0)559 void parseNOSERIAL(size_t &p0){
560 	bool val = getBool(p0);
561 	xmlrig.noserial = val;
562 	size_t pend = tagEnd(p0);
563 	p0 = pend;
564 }
565 
566 //---------------------------------------------------------------------
567 // Parse ASCII, use during xml file creation/testing
568 // prints events as ASCII string vice HEX sequence
569 //---------------------------------------------------------------------
570 
parseASCII(size_t & p0)571 void parseASCII(size_t &p0){
572 	bool val = getBool(p0);
573 	xmlrig.ascii = val;
574 	size_t pend = tagEnd(p0);
575 	p0 = pend;
576 }
577 
578 
579 //---------------------------------------------------------------------
580 // Parse Baudrate, write_delay, post_write_delay, timeout, retries
581 // RTSCTS handshake
582 //---------------------------------------------------------------------
583 
parseBAUDRATE(size_t & p0)584 void parseBAUDRATE(size_t &p0)
585 {
586 	string sVal = getElement(p0);
587 	xmlrig.baud = progdefaults.nBaudRate(sVal.c_str());
588 	size_t pend = tagEnd(p0);
589 	p0 = pend;
590 }
591 
parseSTOPBITS(size_t & p0)592 void parseSTOPBITS(size_t &p0){
593 	int val = getInt(p0);
594 	if (val < 0 || val > 2) val = 2;
595 	xmlrig.stopbits = val;
596 	size_t pend = tagEnd(p0);
597 	p0 = pend;
598 }
599 
parseWRITE_DELAY(size_t & p0)600 void parseWRITE_DELAY(size_t &p0){
601 	int val = getInt(p0);
602 	xmlrig.write_delay = val;
603 	size_t pend = tagEnd(p0);
604 	p0 = pend;
605 }
606 
parseINIT_DELAY(size_t & p0)607 void parseINIT_DELAY(size_t &p0){
608 	int val = getInt(p0);
609 	xmlrig.init_delay = val;
610 	size_t pend = tagEnd(p0);
611 	p0 = pend;
612 }
613 
parseWAIT_FOR_DEVICE(size_t & p0)614 void parseWAIT_FOR_DEVICE(size_t &p0){
615 	int val = getInt(p0);
616 	xmlrig.wait_for_device = val;
617 	size_t pend = tagEnd(p0);
618 	p0 = pend;
619 }
620 
parsePOST_WRITE_DELAY(size_t & p0)621 void parsePOST_WRITE_DELAY(size_t &p0){
622 	int val = getInt(p0);
623 	xmlrig.post_write_delay = val;
624 	size_t pend = tagEnd(p0);
625 	p0 = pend;
626 }
627 
parseRETRIES(size_t & p0)628 void parseRETRIES(size_t &p0){
629 	int val = getInt(p0);
630 	xmlrig.retries = val;
631 	size_t pend = tagEnd(p0);
632 	p0 = pend;
633 }
634 
parseTIMEOUT(size_t & p0)635 void parseTIMEOUT(size_t &p0){
636 	int val = getInt(p0);
637 	xmlrig.timeout = val;
638 	size_t pend = tagEnd(p0);
639 	p0 = pend;
640 }
641 
parseRTSCTS(size_t & p0)642 void parseRTSCTS(size_t &p0){
643 	bool val = getBool(p0);
644 	xmlrig.rtscts = val;
645 	size_t pend = tagEnd(p0);
646 	p0 = pend;
647 }
648 
parseRTSPLUS(size_t & p0)649 void parseRTSPLUS(size_t &p0)
650 {
651 	bool val = getBool(p0);
652 	xmlrig.rts = val;
653 	size_t pend = tagEnd(p0);
654 	p0 = pend;
655 }
656 
parseDTRPLUS(size_t & p0)657 void parseDTRPLUS(size_t &p0)
658 {
659 	bool val = getBool(p0);
660 	xmlrig.dtr = val;
661 	size_t pend = tagEnd(p0);
662 	p0 = pend;
663 }
664 
parseRTSPTT(size_t & p0)665 void parseRTSPTT(size_t &p0)
666 {
667 	bool val = getBool(p0);
668 	xmlrig.rtsptt = val;
669 	size_t pend = tagEnd(p0);
670 	p0 = pend;
671 }
672 
parseDTRPTT(size_t & p0)673 void parseDTRPTT(size_t &p0)
674 {
675 	bool val = getBool(p0);
676 	xmlrig.dtrptt = val;
677 	size_t pend = tagEnd(p0);
678 	p0 = pend;
679 }
680 
parseRESTORE_TIO(size_t & p0)681 void parseRESTORE_TIO(size_t &p0)
682 {
683 	bool val = getBool(p0);
684 	xmlrig.restore_tio = val;
685 	size_t pend = tagEnd(p0);
686 	p0 = pend;
687 }
688 
parseCMDPTT(size_t & p0)689 void parseCMDPTT(size_t &p0) {
690 	bool val = getBool(p0);
691 	xmlrig.cmdptt = val;
692 	size_t pend = tagEnd(p0);
693 	p0 = pend;
694 }
695 
parseECHO(size_t & p0)696 void parseECHO(size_t &p0) {
697 	bool val = getBool(p0);
698 	xmlrig.echo = val;
699 	size_t pend = tagEnd(p0);
700 	p0 = pend;
701 }
702 
parseVSP(size_t & p0)703 void parseVSP(size_t &p0)
704 {
705 	bool val = getBool(p0);
706 	xmlrig.vsp = val;
707 	size_t pend = tagEnd(p0);
708 	p0 = pend;
709 }
710 
parseLOGSTR(size_t & p0)711 void parseLOGSTR(size_t &p0) {
712 	bool val = getBool(p0);
713 	xmlrig.logstr = val;
714 	size_t pend = tagEnd(p0);
715 	p0 = pend;
716 }
717 
parsePOLLINT(size_t & p0)718 void parsePOLLINT(size_t &p0) {
719 	int val = getInt(p0);
720 	if (val < 100) val = 1000;
721 	if (val > 20000) val = 20000;
722 	xmlrig.pollinterval = val;
723 	size_t pend = tagEnd(p0);
724 	p0 = pend;
725 }
726 
parseSMETER(size_t & p0)727 void parseSMETER(size_t &p0) {
728 	string strmeter = getElement(p0);
729 	size_t pend = tagEnd(p0);
730 	p0 = pend;
731 	xmlrig.smeter.clear();
732 	int val, sm;
733 	size_t p = strmeter.find(",");
734 	while ( !strmeter.empty() && (p != string::npos) ) {
735 		val = atoi(&strmeter[0]);
736 		sm = atoi(&strmeter[p+1]);
737 		xmlrig.smeter.push_back(PAIR(val,sm));
738 		p = strmeter.find(";");
739 		if (p == string::npos) strmeter.clear();
740 		else {
741 			strmeter.erase(0, p+1);
742 			p = strmeter.find(",");
743 		}
744 	}
745 	xmlrig.use_smeter = true;
746 }
747 
parsePMETER(size_t & p0)748 void parsePMETER(size_t &p0) {
749 	string strmeter = getElement(p0);
750 	size_t pend = tagEnd(p0);
751 	p0 = pend;
752 	xmlrig.pmeter.clear();
753 	int val, sm;
754 	size_t p = strmeter.find(",");
755 	while ( !strmeter.empty() && (p != string::npos) ) {
756 		val = atoi(&strmeter[0]);
757 		sm = atoi(&strmeter[p+1]);
758 		xmlrig.pmeter.push_back(PAIR(val,sm));
759 		p = strmeter.find(";");
760 		if (p == string::npos) strmeter.clear();
761 		else {
762 			strmeter.erase(0, p+1);
763 			p = strmeter.find(",");
764 		}
765 	}
766 	xmlrig.use_pwrmeter = true;
767 }
768 
parseNOTCH(size_t & p0)769 void parseNOTCH(size_t &p0) {
770 	string strnotch = getElement(p0);
771 	size_t pend = tagEnd(p0);
772 	p0 = pend;
773 	xmlrig.notch.clear();
774 	int val, ntch;
775 	size_t p = strnotch.find(",");
776 	while ( !strnotch.empty() && (p != string::npos) ) {
777 		val = atoi(&strnotch[0]);
778 		ntch = atoi(&strnotch[p+1]);
779 		xmlrig.notch.push_back(PAIR(val,ntch));
780 		p = strnotch.find(";");
781 		if (p == string::npos) strnotch.clear();
782 		else {
783 			strnotch.erase(0, p+1);
784 			p = strnotch.find(",");
785 		}
786 	}
787 	xmlrig.use_notch = true;
788 }
789 
parsePWRLEVEL(size_t & p0)790 void parsePWRLEVEL(size_t &p0) {
791 	string strpwrlevel = getElement(p0);
792 	size_t pend = tagEnd(p0);
793 	p0 = pend;
794 	xmlrig.pwrlevel.clear();
795 	int val, pwr;
796 	float min = 500, max = 0;
797 	size_t p = strpwrlevel.find(",");
798 	while ( !strpwrlevel.empty() && (p != string::npos) ) {
799 		val = atoi(&strpwrlevel[0]);
800 		pwr = atoi(&strpwrlevel[p+1]);
801 		if (pwr < min) min = pwr;
802 		if (pwr > max) max = pwr;
803 		xmlrig.pwrlevel.push_back(PAIR(val,pwr));
804 		p = strpwrlevel.find(";");
805 		if (p == string::npos) strpwrlevel.clear();
806 		else {
807 			strpwrlevel.erase(0, p+1);
808 			p = strpwrlevel.find(",");
809 		}
810 	}
811 	pwr_level->range(min, max);
812 	xmlrig.use_pwrlevel = true;
813 }
814 
815 //---------------------------------------------------------------------
816 // Parse IOS (serial stream format) definitions
817 //---------------------------------------------------------------------
818 
parseIOSsize(size_t & p0)819 void parseIOSsize(size_t &p0)
820 {
821 	iosTemp.size = getInt(p0);
822 }
823 
parseIOSbytes(size_t & p0)824 void parseIOSbytes(size_t &p0)
825 {
826 	if (iosTemp.data.size == 0)
827 		iosTemp.str1.append(getBytes(p0));
828 	else
829 		iosTemp.str2.append(getBytes(p0));
830 }
831 
parseIOSbyte(size_t & p0)832 void parseIOSbyte(size_t &p0)
833 {
834 	if (iosTemp.data.size == 0)
835 		iosTemp.str1 += getByte(p0);
836 	else
837 		iosTemp.str2 += getByte(p0);
838 }
839 
parseIOSstring(size_t & p0)840 void parseIOSstring(size_t &p0)
841 {
842 	if (iosTemp.data.size == 0)
843 		iosTemp.str1 += getElement(p0);
844 	else
845 		iosTemp.str2 += getElement(p0);
846 }
847 
parseIOSint(size_t & p0)848 void parseIOSint(size_t &p0)
849 {
850 	if (iosTemp.data.size == 0)
851 		iosTemp.str1 += (char)(getInt(p0) & 0xFF);
852 	else
853 		iosTemp.str2 += (char)(getInt(p0) & 0xFF);
854 }
855 
parseDTYPE(size_t & p1)856 void parseDTYPE(size_t &p1)
857 {
858 	print(p1,2);
859 	iosTemp.data.dtype = getElement(p1);
860 }
861 
parseDSIZE(size_t & p1)862 void parseDSIZE(size_t &p1)
863 {
864 	print(p1,2);
865 	iosTemp.data.size = getInt(p1);
866 }
867 
parseDMAX(size_t & p1)868 void parseDMAX(size_t &p1)
869 {
870 	print(p1,2);
871 	iosTemp.data.max = getInt(p1);
872 }
873 
parseDMIN(size_t & p1)874 void parseDMIN(size_t &p1)
875 {
876 	print(p1,2);
877 	iosTemp.data.min = getInt(p1);
878 }
879 
parseDRESOL(size_t & p1)880 void parseDRESOL(size_t &p1)
881 {
882 	print(p1,2);
883 	iosTemp.data.resolution = getFloat(p1);
884 }
885 
parseDREV(size_t & p1)886 void parseDREV(size_t &p1)
887 {
888 	print(p1,2);
889 	iosTemp.data.reverse = getBool(p1);
890 }
891 
parseDMAKS(size_t & p1)892 void parseDMAKS(size_t &p1)
893 {
894 	print(p1,2);
895 	iosTemp.data.andmask = getInt(p1);
896 }
897 
parseDSHIFT(size_t & p1)898 void parseDSHIFT(size_t &p1)
899 {
900 	print(p1,2);
901 	iosTemp.data.shiftbits = getInt(p1);
902 }
903 
parseIOSdata(size_t & p0)904 void parseIOSdata(size_t &p0)
905 {
906 	size_t pend = tagEnd(p0);
907 	size_t p1;
908 	TAGS *pv;
909 
910 	p1 = nextTag(p0);
911 	while (p1 < pend) {
912 		pv = datatags;
913 		while (pv->tag) {
914 			if (strXML.find(pv->tag, p1) == p1)
915 				break;
916 			pv++;
917 		}
918 		if (pv->fp) {
919 			print(p1, 1);
920 			(pv->fp)(p1);
921 			p1 = tagEnd(p1);
922 		} else {
923 			LOG_ERROR("Invalid tag: %s", strXML.substr(p1, 10).c_str());
924 			parseDISCARD(p1);
925 		}
926 		p1 = nextTag(p1);
927 	}
928 }
929 
parseIOSinfo(size_t & p0)930 void parseIOSinfo(size_t &p0)
931 {
932 	string strR = getElement(p0);
933 	if (strR.empty()) return;
934 	iosTemp.info = strR;
935 }
936 
parseIOSok(size_t & p0)937 void parseIOSok(size_t &p0)
938 {
939 	string strR = getElement(p0);
940 	if (strR.empty()) return;
941 	iosTemp.ok = strR;
942 }
943 
parseIOSbad(size_t & p0)944 void parseIOSbad(size_t &p0)
945 {
946 	string strR = getElement(p0);
947 	if (strR.empty()) return;
948 	iosTemp.bad = strR;
949 }
950 
parseIOSsymbol(size_t & p0)951 void parseIOSsymbol(size_t &p0)
952 {
953 	string strR = getElement(p0);
954 	if (strR.empty()) return;
955 	iosTemp.SYMBOL = strR;
956 }
957 
parseIOSfill(size_t & p0)958 void parseIOSfill(size_t &p0)
959 {
960 	if (iosTemp.data.size == 0)
961 		iosTemp.fill1 = getInt(p0);
962 	else
963 		iosTemp.fill2 = getInt(p0);
964 }
965 
966 //=======================================================================
967 
parseIOS(size_t & p0,TAGS * valid)968 bool parseIOS(size_t &p0, TAGS *valid)
969 {
970 	size_t pend = tagEnd(p0);
971 	size_t p1;
972 	TAGS *pv;
973 
974 	print(p0,0);
975 
976 	iosTemp.clear();
977 	p1 = nextTag(p0);
978 	while (p1 < pend) {
979 		pv = valid;
980 		while (pv->tag) {
981 			if (strXML.find(pv->tag, p1) == p1)
982 				break;
983 			pv++;
984 		}
985 		if (pv->fp) {
986 			print(p1, 1);
987 			(pv->fp)(p1);
988 			p1 = tagEnd(p1);
989 		} else {
990 			LOG_ERROR("Invalid tag: %s", strXML.substr(p1, 10).c_str());
991 			parseDISCARD(p1);
992 		}
993 		p1 = nextTag(p1);
994 	}
995 	p0 = pend;
996 	return (!iosTemp.SYMBOL.empty());
997 }
998 
parseCOMMAND(size_t & p0)999 void parseCOMMAND(size_t &p0)
1000 {
1001 	if (parseIOS(p0, commandtags))
1002 		commands.push_back(iosTemp);
1003 }
1004 
parseREPLY(size_t & p0)1005 void parseREPLY(size_t &p0)
1006 {
1007 	if (parseIOS(p0, replytags))
1008 		reply.push_back(iosTemp);
1009 }
1010 
parseRIGDEF(size_t & p0)1011 void parseRIGDEF(size_t &p0)
1012 {
1013 	print(p0,0);
1014 	size_t p1 = tagEnd(p0);
1015 	if (p1 != string::npos)
1016 		strXML.erase(p1);
1017 }
1018 
parseDISCARD(size_t & p0)1019 void parseDISCARD(size_t &p0)
1020 {
1021 	size_t pend = tagEnd(p0);
1022 	if (pend == string::npos) p0++;
1023 	else p0 = pend;
1024 }
1025 
parseXML()1026 void parseXML()
1027 {
1028 	size_t p0 = 0;
1029 	TAGS *pValid = rigdeftags;
1030 
1031 	p0 = strXML.find("<");
1032 	while (p0 != string::npos) {
1033 		pValid = rigdeftags;
1034 		while (pValid->tag) {
1035 			if (strXML.find(pValid->tag, p0) == p0)
1036 				break;
1037 			pValid++;
1038 		}
1039 		if (pValid->tag) {
1040 			(pValid->fp)(p0);
1041 		 } else {
1042 			LOG_ERROR("Invalid tag: %s", strXML.substr(p0, 10).c_str());
1043 			parseDISCARD(p0);
1044 		}
1045 		p0 = nextTag(p0);
1046 	}
1047 }
1048 
remove_comments()1049 bool remove_comments()
1050 {
1051 	size_t p0 = 0;
1052 	size_t p1 = 0;
1053 
1054 // remove comments from xml text
1055 	while ((p0 = strXML.find("<!--")) != string::npos) {
1056 		p1 = strXML.find("-->", p0);
1057 		if (p1 == string::npos) {
1058 			fl_alert2("Corrupt rig XML definition file\nMismatched comment tags!");
1059 			return false;
1060 		}
1061 		strXML.erase(p0, p1 - p0 + 3);
1062 	}
1063 	if (strXML.find("-->") != string::npos) {
1064 		fl_alert2("Corrupt rig XML definition file\nMismatched comment tags!");
1065 		return false;
1066 	}
1067 	return true;
1068 }
1069 
testXML()1070 bool testXML()
1071 {
1072 	if (!remove_comments()) return false;
1073 
1074 	return true;
1075 }
1076 
readRigXML()1077 bool readRigXML()
1078 {
1079 	char szLine[256];
1080 	int lines = 0;
1081 
1082 	commands.clear();
1083 	reply.clear();
1084 	lmodes.clear();
1085 	lmodeCMD.clear();
1086 	lmodeREPLY.clear();
1087 	lbws.clear();
1088 	lbwCMD.clear();
1089 	lbwREPLY.clear();
1090 	LSBmodes.clear();
1091 	strXML = "";
1092 
1093 	ifstream xmlfile(progdefaults.XmlRigFilename.c_str(), ios::in);
1094 	if (xmlfile) {
1095 		while (!xmlfile.eof()) {
1096 			lines++;
1097 			memset(szLine, 0, sizeof(szLine));
1098 			xmlfile.getline(szLine,255);
1099 			strXML.append(szLine);
1100 		}
1101 		xmlfile.close();
1102 		if (testXML()) {
1103 			parseXML();
1104 			xmlrig.xmlok = true;
1105 			return true;
1106 		}
1107 	}
1108 	return false;
1109 }
1110 
selectRigXmlFilename()1111 void selectRigXmlFilename()
1112 {
1113 	string deffilename;
1114 	deffilename = progdefaults.XmlRigFilename;
1115 	const char *p = FSEL::select(_("Open rig xml file"), _("Fldigi rig xml definition file\t*.xml"), deffilename.c_str());
1116 	if (!p) return;
1117 	if (!*p) return;
1118 
1119 	progdefaults.XmlRigFilename = p;
1120 	txtXmlRigFilename->value(fl_filename_name(p));
1121 	loadRigXmlFile();
1122 }
1123 
loadRigXmlFile(void)1124 void loadRigXmlFile(void)
1125 {
1126 	rigCAT_close();
1127 	readRigXML();
1128 	rigCAT_defaults();
1129 }
1130