fxsdk/libfxlink/filter.c
Lephenixnoir 50997a8b75
very crude Windows build (WIP): disable fxlink TUI, gdb bridge
There is no direct replacement for poll() in the Windows API, so I'm
gonna disable the fxlink TUI for now and maybe later figure out how to
do something equivalent, even if more brute-forcey.
2024-09-14 07:26:56 +02:00

186 lines
4.7 KiB
C

//---------------------------------------------------------------------------//
// ==>/[_]\ fxlink: A community communication tool for CASIO calculators. //
// |:::| Made by Lephe' as part of the fxSDK. //
// \___/ License: MIT <https://opensource.org/licenses/MIT> //
//---------------------------------------------------------------------------//
#include <fxlink/filter.h>
#include <fxlink/logging.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
//---
// Filter parser
//---
/* Identify property separating characters to be skipped */
static bool issep(int c)
{
return (c == ' ' || c == '\t' || c == '\n' || c == ',');
}
/* Identify valid word characters for the filter */
static bool isword(int c)
{
return c && !strchr(" \t\n,=", c);
}
/* Copy the next word in the string, assumes word is non-empty */
static char *read_word(char const **input)
{
char const *str = *input;
while(**input && isword(**input)) (*input)++;
char *rc = malloc(*input - str + 1);
if(!rc)
return NULL;
memcpy(rc, str, *input - str);
rc[*input - str] = 0;
return rc;
}
/* Reads a property from the input source. Advances *input and sets *name and
*value to newly-allocated copies of the name and (optional) value of the
property (T_PROP). Both should be free()'d after use. At the end of the
input, returns false and sets *name = *value = NULL. */
static bool read_property(char const **input, char **name, char **value)
{
*name = *value = NULL;
while(issep(**input))
(*input)++;
if(!**input)
return false;
if(!isword(**input)) {
elog("expected property name in filter, found '%c'; stopping\n",
**input);
return false;
}
*name = read_word(input);
if(**input == '=') {
(*input)++;
*value = read_word(input);
}
return true;
}
struct fxlink_filter *fxlink_filter_parse(char const *input)
{
char *name=NULL, *value=NULL;
struct fxlink_filter *filter = calloc(1, sizeof *filter);
if(!filter)
return NULL;
while(read_property(&input, &name, &value)) {
/* Add a new property to the current option */
if(!strcmp(name, "p7") && !value)
filter->p7 = true;
else if(!strcmp(name, "mass_storage") && !value)
filter->mass_storage = true;
else if(!strcmp(name, "series_cg") && !value)
filter->series_cg = true;
else if(!strcmp(name, "series_g3") && !value)
filter->series_g3 = true;
else if(!strcmp(name, "intf_fxlink") && !value)
filter->intf_fxlink = true;
else if(!strcmp(name, "intf_cesg502") && !value)
filter->intf_cesg502 = true;
else if(!strcmp(name, "serial") && value)
filter->serial = strdup(value);
else if(!strcmp(name, "serial_number") && value) // Old name
filter->serial = strdup(value);
else wlog("ignoring invalid filter property: '%s' (%s value)\n",
name, value ? "with" : "without");
free(name);
free(value);
}
return filter;
}
//---
// Filtering API
//---
void fxlink_filter_clean_libusb(struct fxlink_filter *filter)
{
if(!filter)
return;
/* Suppress series_cg and series_g3, which are based off the SCSI metadata
provided only to UDisks2 */
if(filter->series_cg) {
wlog("ignoring series_cg in libusb filter (cannot be detected)\n");
filter->series_cg = false;
}
if(filter->series_g3) {
wlog("ignoring series_g3 in libusb filter (cannot be detected)\n");
filter->series_g3 = false;
}
}
void fxlink_filter_clean_udisks2(struct fxlink_filter *filter)
{
/* Every property can be used */
(void)filter;
}
bool fxlink_filter_match(
struct fxlink_filter const *props,
struct fxlink_filter const *filter)
{
/* No filter is a pass-through */
if(!filter)
return true;
if(filter->p7 && !props->p7)
return false;
if(filter->mass_storage && !props->mass_storage)
return false;
if(filter->intf_fxlink && !props->intf_fxlink)
return false;
if(filter->intf_cesg502 && !props->intf_cesg502)
return false;
if(filter->series_cg && !props->series_cg)
return false;
if(filter->series_g3 && !props->series_g3)
return false;
if(filter->serial &&
(!props->serial || strcmp(filter->serial, props->serial)))
return false;
return true;
}
void fxlink_filter_print(FILE *fp, struct fxlink_filter const *filter)
{
#define output(...) { \
if(sep) fprintf(fp, ", "); \
fprintf(fp, __VA_ARGS__); \
sep = true; \
}
bool sep = false;
if(filter->p7)
output("p7");
if(filter->mass_storage)
output("mass_storage");
if(filter->intf_fxlink)
output("intf_fxlink");
if(filter->intf_cesg502)
output("intf_cesg502");
if(filter->series_cg)
output("series_cg");
if(filter->series_g3)
output("series_g3");
if(filter->serial)
output("serial=%s", filter->serial);
}
void fxlink_filter_free(struct fxlink_filter *filter)
{
if(filter)
free(filter->serial);
free(filter);
}