parse_config port to rust

This commit is contained in:
Greg Shuflin 2021-03-03 00:49:57 -08:00
parent 5658759cf3
commit 3f4b18368b
2 changed files with 91 additions and 112 deletions

106
radio.c
View File

@ -35,109 +35,3 @@
#include "radio.h" #include "radio.h"
#include "util.h" #include "util.h"
/*
typedef struct { char* ident; radio_device_t* device; } radio_tab_t;
static radio_tab_t radio_tab[] = {
{ "DR780", &radio_md380 }, // TYT MD-380, Retevis RT3, RT8
{ "MD390", &radio_md390 }, // TYT MD-390
{ "MD-UV380", &radio_uv380 }, // TYT MD-UV380
{ "MD-UV390", &radio_uv390 }, // TYT MD-UV390, Retevis RT3S
{ "2017", &radio_md2017 }, // TYT MD-2017, Retevis RT82
{ "MD9600", &radio_md9600 }, // TYT MD-9600
{ "BF-5R", &radio_rd5r }, // Baofeng RD-5R, TD-5R
{ "1801", &radio_dm1801 }, // Baofeng DM-1801
{ "DM-1701", &radio_rt84 }, // Baofeng DM-1701, Retevis RT84
{ "MD-760P", &radio_gd77 }, // Radioddity GD-77, version 3.1.1 and later
{ "D868UVE", &radio_d868uv }, // Anytone AT-D868UV
{ "D878UV", &radio_d878uv }, // Anytone AT-D878UV
{ "D6X2UV", &radio_dmr6x2 }, // BTECH DMR-6x2
{ "ZD3688", &radio_d900 }, // Zastone D900
{ "TP660", &radio_dp880 }, // Zastone DP880
{ "ZN><:", &radio_rt27d }, // Radtel RT-27D
{ 0, 0 }
};
*/
//
// Read the configuration from text file, and modify the firmware.
//
void radio_parse_config(radio_device_t* device, const char *filename)
{
FILE *conf;
char line [256], *p, *v;
int table_id = 0, table_dirty = 0;
fprintf(stderr, "Read configuration from file '%s'.\n", filename);
conf = fopen(filename, "r");
if (! conf) {
perror(filename);
exit(-1);
}
device->channel_count = 0;
while (fgets(line, sizeof(line), conf)) {
line[sizeof(line)-1] = 0;
// Strip comments.
v = strchr(line, '#');
if (v)
*v = 0;
// Strip trailing spaces and newline.
v = line + strlen(line) - 1;
while (v >= line && (*v=='\n' || *v=='\r' || *v==' ' || *v=='\t'))
*v-- = 0;
// Ignore comments and empty lines.
p = line;
if (*p == 0)
continue;
if (*p != ' ') {
// Table finished.
table_id = 0;
// Find the value.
v = strchr(p, ':');
if (! v) {
// Table header: get table type.
table_id = device->parse_header(device, p);
if (! table_id) {
badline: fprintf(stderr, "Invalid line: '%s'\n", line);
exit(-1);
}
table_dirty = 0;
continue;
}
// Parameter.
*v++ = 0;
// Skip spaces.
while (*v == ' ' || *v == '\t')
v++;
device->parse_parameter(device, p, v);
} else {
// Table row or comment.
// Skip spaces.
// Ignore comments and empty lines.
while (*p == ' ' || *p == '\t')
p++;
if (*p == '#' || *p == 0)
continue;
if (! table_id) {
goto badline;
}
if (! device->parse_row(device, table_id, ! table_dirty, p)) {
goto badline;
}
table_dirty = 1;
}
}
fclose(conf);
device->update_timestamp(device);
}

View File

@ -37,8 +37,6 @@ pub static mut radio_mem: [u8; 1024*1024*2] = [0; 1024*1024*2];
extern { extern {
fn radio_parse_config(device: *const radio_device_t, filename: *const c_char);
fn dfu_init(vid: c_uint, pid: c_uint) -> *const c_char; fn dfu_init(vid: c_uint, pid: c_uint) -> *const c_char;
fn dfu_reboot(); fn dfu_reboot();
fn dfu_close(); fn dfu_close();
@ -311,12 +309,99 @@ pub fn save_image(radio: &Radio, filename: &str) {
} }
} }
/// Read the configuration from text file, and modify the firmware. /// Read the configuration from a text file, and modify the firmware.
pub fn parse_config(radio: &Radio, filename: &str) { pub fn parse_config(radio: &Radio, filename: &str) {
let device = radio.ptr; use std::io::{BufRead, BufReader};
let filename = CString::new(filename.to_string()).unwrap();
let device = radio.ptr as *mut radio_device_t;
let parse_header_fn = unsafe {
(*device).parse_header.unwrap()
};
let parse_parameter_fn = unsafe {
(*device).parse_parameter.unwrap()
};
let parse_row_fn = unsafe {
(*device).parse_row.unwrap()
};
let update_timestamp_fn = unsafe {
(*device).update_timestamp.unwrap()
};
eprintln!("Read configuration from file '{}'.", filename);
let file = std::fs::File::open(filename).unwrap();
let file = BufReader::new(file);
let mut table_id: c_int = 0;
let mut table_dirty: c_int = 0;
for line in file.lines() {
let line = line.unwrap();
// Strip text after comment marker '#'
let trimmed_line = line
.split('#')
.next()
.unwrap()
.trim_end();
// Skip comments and blank lines
if trimmed_line.is_empty() {
continue;
}
// Table row
if trimmed_line.chars().nth(0) == Some(' ') {
if table_id == 0 {
eprintln!("Invalid line: '{}'", line);
exit(-1);
}
let trimmed_more = CString::new(trimmed_line.trim_start()).unwrap();
let ptr = trimmed_more.as_ptr() as *mut c_char;
let output = unsafe { parse_row_fn(device, table_id, !table_dirty, ptr) };
if output == 0 {
eprintln!("Invalid line: '{}'", line);
exit(-1);
}
table_dirty = 1;
} else {
// Table finished
table_id = 0;
// Find the value
if let Some(colon_byte_idx) = line.find(':') {
let (param_str, value_str) = line.split_at(colon_byte_idx);
let stripped_value_str = value_str.strip_prefix(':').unwrap();
let param_c_str = CString::new(param_str.trim_start()).unwrap();
let param_ptr = param_c_str.as_ptr() as *mut c_char;
let value_c_str = CString::new(stripped_value_str.trim_start()).unwrap();
let value_ptr = value_c_str.as_ptr() as *mut c_char;
unsafe { unsafe {
radio_parse_config(device, filename.as_ptr()) parse_parameter_fn(device, param_ptr, value_ptr);
}
} else { // Table header
let c_line = CString::new(trimmed_line).unwrap();
let ptr = c_line.as_ptr() as *mut c_char;
table_id = unsafe { parse_header_fn(device, ptr) };
if table_id == 0 {
eprintln!("Invalid line: '{}'", line);
exit(-1);
}
table_dirty = 0;
}
}
}
unsafe {
update_timestamp_fn(device);
} }
} }