Move useful CMDBIT/part functions from developer_opts.c to avrpart.c
This commit is contained in:
parent
62dcc2e6e8
commit
004b46b594
342
src/avrpart.c
342
src/avrpart.c
|
@ -71,6 +71,21 @@ void avr_free_opcode(OPCODE * op)
|
|||
free(op);
|
||||
}
|
||||
|
||||
|
||||
// returns position 0..31 of highest bit set or INT_MIN if no bit is set
|
||||
int intlog2(unsigned int n) {
|
||||
int ret;
|
||||
|
||||
if(!n)
|
||||
return INT_MIN;
|
||||
|
||||
for(ret = 0; n >>= 1; ret++)
|
||||
continue;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* avr_set_bits()
|
||||
*
|
||||
|
@ -126,6 +141,101 @@ int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* avr_set_addr_mem()
|
||||
*
|
||||
* Set address bits in the specified command based on the memory, opcode and
|
||||
* address; addr must be a word address for flash or, for all other memories,
|
||||
* a byte address; returns 0 on success and -1 on error (no memory or no
|
||||
* opcode) or, if positive, bn+1 where bn is bit number of the highest
|
||||
* necessary bit that the opcode does not provide.
|
||||
*/
|
||||
int avr_set_addr_mem(AVRMEM *mem, int opnum, unsigned char *cmd, unsigned long addr) {
|
||||
int ret, isflash, lo, hi, memsize, pagesize;
|
||||
OPCODE *op;
|
||||
|
||||
if(!mem)
|
||||
return -1;
|
||||
|
||||
if(!(op = mem->op[opnum]))
|
||||
return -1;
|
||||
|
||||
isflash = !strcmp(mem->desc, "flash"); // ISP parts have only one flash-like memory
|
||||
memsize = mem->size >> isflash; // word addresses for flash
|
||||
pagesize = mem->page_size >> isflash;
|
||||
|
||||
// compute range lo..hi of needed address bits
|
||||
switch(opnum) {
|
||||
case AVR_OP_READ:
|
||||
case AVR_OP_WRITE:
|
||||
case AVR_OP_READ_LO:
|
||||
case AVR_OP_READ_HI:
|
||||
case AVR_OP_WRITE_LO:
|
||||
case AVR_OP_WRITE_HI:
|
||||
lo = 0;
|
||||
hi = intlog2(memsize-1); // memsize = 1 implies no addr bit is needed
|
||||
break;
|
||||
|
||||
case AVR_OP_LOADPAGE_LO:
|
||||
case AVR_OP_LOADPAGE_HI:
|
||||
lo = 0;
|
||||
hi = intlog2(pagesize-1);
|
||||
break;
|
||||
|
||||
case AVR_OP_LOAD_EXT_ADDR:
|
||||
lo = 16;
|
||||
hi = intlog2(memsize-1);
|
||||
break;
|
||||
|
||||
case AVR_OP_WRITEPAGE:
|
||||
lo = intlog2(pagesize);
|
||||
hi = intlog2(memsize-1);
|
||||
break;
|
||||
|
||||
case AVR_OP_CHIP_ERASE:
|
||||
case AVR_OP_PGM_ENABLE:
|
||||
default:
|
||||
lo = 0;
|
||||
hi = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
// Unless it's load extended address, ISP chips only deal with 16 bit addresses
|
||||
if(opnum != AVR_OP_LOAD_EXT_ADDR && hi > 15)
|
||||
hi = 15;
|
||||
|
||||
unsigned char avail[32];
|
||||
memset(avail, 0, sizeof avail);
|
||||
|
||||
for(int i=0; i<32; i++) {
|
||||
if(op->bit[i].type == AVR_CMDBIT_ADDRESS) {
|
||||
int bitno, j, bit;
|
||||
unsigned char mask;
|
||||
|
||||
bitno = op->bit[i].bitno & 31;
|
||||
j = 3 - i / 8;
|
||||
bit = i % 8;
|
||||
mask = 1 << bit;
|
||||
avail[bitno] = 1;
|
||||
|
||||
// 'a' bit with number outside bit range [lo, hi] is set to 0
|
||||
if (bitno >= lo && bitno <= hi? (addr >> bitno) & 1: 0)
|
||||
cmd[j] = cmd[j] | mask;
|
||||
else
|
||||
cmd[j] = cmd[j] & ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
if(lo >= 0 && hi < 32 && lo <= hi)
|
||||
for(int bn=lo; bn <= hi; bn++)
|
||||
if(!avail[bn]) // necessary bit bn misses in opcode
|
||||
ret = bn+1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* avr_set_input()
|
||||
*
|
||||
|
@ -239,7 +349,6 @@ static char * bittype(int type)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/***
|
||||
*** Elementary functions dealing with AVRMEM structures
|
||||
***/
|
||||
|
@ -556,12 +665,10 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
|
|||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Elementary functions dealing with AVRPART structures
|
||||
*/
|
||||
|
||||
|
||||
AVRPART * avr_new_part(void)
|
||||
{
|
||||
AVRPART * p;
|
||||
|
@ -819,3 +926,232 @@ void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose)
|
|||
if (buf)
|
||||
free(buf);
|
||||
}
|
||||
|
||||
|
||||
char cmdbitchar(CMDBIT cb) {
|
||||
switch(cb.type) {
|
||||
case AVR_CMDBIT_IGNORE:
|
||||
return 'x';
|
||||
case AVR_CMDBIT_VALUE:
|
||||
return cb.value? '1': '0';
|
||||
case AVR_CMDBIT_ADDRESS:
|
||||
return 'a';
|
||||
case AVR_CMDBIT_INPUT:
|
||||
return 'i';
|
||||
case AVR_CMDBIT_OUTPUT:
|
||||
return 'o';
|
||||
default:
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char *cmdbitstr(CMDBIT cb) {
|
||||
char space[32];
|
||||
|
||||
*space = cmdbitchar(cb);
|
||||
if(*space == 'a')
|
||||
sprintf(space+1, "%d", cb.bitno);
|
||||
else
|
||||
space[1] = 0;
|
||||
|
||||
return strdup(space);
|
||||
}
|
||||
|
||||
|
||||
const char *opcodename(int opnum) {
|
||||
switch(opnum) {
|
||||
case AVR_OP_READ:
|
||||
return "read";
|
||||
case AVR_OP_WRITE:
|
||||
return "write";
|
||||
case AVR_OP_READ_LO:
|
||||
return "read_lo";
|
||||
case AVR_OP_READ_HI:
|
||||
return "read_hi";
|
||||
case AVR_OP_WRITE_LO:
|
||||
return "write_lo";
|
||||
case AVR_OP_WRITE_HI:
|
||||
return "write_hi";
|
||||
case AVR_OP_LOADPAGE_LO:
|
||||
return "loadpage_lo";
|
||||
case AVR_OP_LOADPAGE_HI:
|
||||
return "loadpage_hi";
|
||||
case AVR_OP_LOAD_EXT_ADDR:
|
||||
return "load_ext_addr";
|
||||
case AVR_OP_WRITEPAGE:
|
||||
return "writepage";
|
||||
case AVR_OP_CHIP_ERASE:
|
||||
return "chip_erase";
|
||||
case AVR_OP_PGM_ENABLE:
|
||||
return "pgm_enable";
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Unique string representation of an opcode
|
||||
char *opcode2str(OPCODE *op, int opnum, int detailed) {
|
||||
char cb, space[1024], *sp = space;
|
||||
int compact = 1;
|
||||
|
||||
if(!op)
|
||||
return strdup("NULL");
|
||||
|
||||
// Can the opcode be printed in a compact way? Only if address bits are systematic.
|
||||
for(int i=31; i >= 0; i--)
|
||||
if(op->bit[i].type == AVR_CMDBIT_ADDRESS)
|
||||
if(i<8 || i>23 || op->bit[i].bitno != (opnum == AVR_OP_LOAD_EXT_ADDR? i+8: i-8))
|
||||
compact = 0;
|
||||
|
||||
if(detailed)
|
||||
*sp++ = '"';
|
||||
|
||||
for(int i=31; i >= 0; i--) {
|
||||
*sp++ = cb = cmdbitchar(op->bit[i]);
|
||||
if(compact) {
|
||||
if(i && i%8 == 0)
|
||||
*sp++ = '-', *sp++ = '-';
|
||||
else if(i && i%4 == 0)
|
||||
*sp++ = '.';
|
||||
} else {
|
||||
if(cb == 'a') {
|
||||
sprintf(sp, "%d", op->bit[i].bitno);
|
||||
sp += strlen(sp);
|
||||
}
|
||||
if(i) {
|
||||
if(detailed)
|
||||
*sp++ = ' ';
|
||||
if(i%8 == 0)
|
||||
*sp++ = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
if(detailed)
|
||||
*sp++ = '"';
|
||||
*sp = 0;
|
||||
|
||||
return strdup(space);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Match STRING against the partname pattern PATTERN, returning 1 if it
|
||||
* matches, 0 if not. NOTE: part_match() is a modified old copy of !fnmatch()
|
||||
* from the GNU C Library (published under GLP v2). Used for portability.
|
||||
*/
|
||||
|
||||
inline static int fold(int c) {
|
||||
return (c >= 'A' && c <= 'Z')? c+('a'-'A'): c;
|
||||
}
|
||||
|
||||
int part_match(const char *pattern, const char *string) {
|
||||
unsigned char c;
|
||||
const char *p = pattern, *n = string;
|
||||
|
||||
if(!*n) // AVRDUDE specialty: empty string never matches
|
||||
return 0;
|
||||
|
||||
while((c = fold(*p++))) {
|
||||
switch(c) {
|
||||
case '?':
|
||||
if(*n == 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
c = fold(*p++);
|
||||
if(fold(*n) != c)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case '*':
|
||||
for(c = *p++; c == '?' || c == '*'; c = *p++)
|
||||
if(c == '?' && *n++ == 0)
|
||||
return 0;
|
||||
|
||||
if(c == 0)
|
||||
return 1;
|
||||
|
||||
{
|
||||
unsigned char c1 = fold(c == '\\'? *p : c); // This char
|
||||
|
||||
for(--p; *n; ++n) // Recursively check reminder of string for *
|
||||
if((c == '[' || fold(*n) == c1) && part_match(p, n) == 1)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case '[':
|
||||
{
|
||||
int negate;
|
||||
|
||||
if(*n == 0)
|
||||
return 0;
|
||||
|
||||
negate = (*p == '!' || *p == '^');
|
||||
if(negate)
|
||||
++p;
|
||||
|
||||
c = *p++;
|
||||
for(;;) {
|
||||
unsigned char cstart = c, cend = c;
|
||||
|
||||
if(c == '\\')
|
||||
cstart = cend = *p++;
|
||||
|
||||
cstart = cend = fold(cstart);
|
||||
|
||||
if(c == 0) // [ (unterminated)
|
||||
return 0;
|
||||
|
||||
c = *p++;
|
||||
c = fold(c);
|
||||
|
||||
if(c == '-' && *p != ']') {
|
||||
cend = *p++;
|
||||
if(cend == '\\')
|
||||
cend = *p++;
|
||||
if(cend == 0)
|
||||
return 0;
|
||||
cend = fold(cend);
|
||||
|
||||
c = *p++;
|
||||
}
|
||||
|
||||
if(fold(*n) >= cstart && fold(*n) <= cend)
|
||||
goto matched;
|
||||
|
||||
if(c == ']')
|
||||
break;
|
||||
}
|
||||
if(!negate)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
matched:;
|
||||
while(c != ']') { // Skip the rest of the [...] that already matched
|
||||
|
||||
if(c == 0) // [... (unterminated)
|
||||
return 0;
|
||||
|
||||
c = *p++;
|
||||
if(c == '\\') // XXX 1003.2d11 is unclear if this is right
|
||||
++p;
|
||||
}
|
||||
if(negate)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if(c != fold(*n))
|
||||
return 0;
|
||||
}
|
||||
|
||||
++n;
|
||||
}
|
||||
|
||||
return *n == 0;
|
||||
}
|
||||
|
|
|
@ -51,114 +51,6 @@
|
|||
#include "developer_opts.h"
|
||||
#include "developer_opts_private.h"
|
||||
|
||||
char cmdbitchar(CMDBIT cb) {
|
||||
switch(cb.type) {
|
||||
case AVR_CMDBIT_IGNORE:
|
||||
return 'x';
|
||||
case AVR_CMDBIT_VALUE:
|
||||
return cb.value? '1': '0';
|
||||
case AVR_CMDBIT_ADDRESS:
|
||||
return 'a';
|
||||
case AVR_CMDBIT_INPUT:
|
||||
return 'i';
|
||||
case AVR_CMDBIT_OUTPUT:
|
||||
return 'o';
|
||||
default:
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char *cmdbitstr(CMDBIT cb) {
|
||||
char space[32];
|
||||
|
||||
*space = cmdbitchar(cb);
|
||||
if(*space == 'a')
|
||||
sprintf(space+1, "%d", cb.bitno);
|
||||
else
|
||||
space[1] = 0;
|
||||
|
||||
return strdup(space);
|
||||
}
|
||||
|
||||
|
||||
const char *opcodename(int opnum) {
|
||||
switch(opnum) {
|
||||
case AVR_OP_READ:
|
||||
return "read";
|
||||
case AVR_OP_WRITE:
|
||||
return "write";
|
||||
case AVR_OP_READ_LO:
|
||||
return "read_lo";
|
||||
case AVR_OP_READ_HI:
|
||||
return "read_hi";
|
||||
case AVR_OP_WRITE_LO:
|
||||
return "write_lo";
|
||||
case AVR_OP_WRITE_HI:
|
||||
return "write_hi";
|
||||
case AVR_OP_LOADPAGE_LO:
|
||||
return "loadpage_lo";
|
||||
case AVR_OP_LOADPAGE_HI:
|
||||
return "loadpage_hi";
|
||||
case AVR_OP_LOAD_EXT_ADDR:
|
||||
return "load_ext_addr";
|
||||
case AVR_OP_WRITEPAGE:
|
||||
return "writepage";
|
||||
case AVR_OP_CHIP_ERASE:
|
||||
return "chip_erase";
|
||||
case AVR_OP_PGM_ENABLE:
|
||||
return "pgm_enable";
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Unique string representation of an opcode
|
||||
char *opcode2str(OPCODE *op, int opnum, int detailed) {
|
||||
char cb, space[1024], *sp = space;
|
||||
int compact = 1;
|
||||
|
||||
if(!op)
|
||||
return strdup("NULL");
|
||||
|
||||
// Can the opcode be printed in a compact way? Only if address bits are systematic.
|
||||
for(int i=31; i >= 0; i--)
|
||||
if(op->bit[i].type == AVR_CMDBIT_ADDRESS)
|
||||
if(i<8 || i>23 || op->bit[i].bitno != (opnum == AVR_OP_LOAD_EXT_ADDR? i+8: i-8))
|
||||
compact = 0;
|
||||
|
||||
if(detailed)
|
||||
*sp++ = '"';
|
||||
|
||||
for(int i=31; i >= 0; i--) {
|
||||
*sp++ = cb = cmdbitchar(op->bit[i]);
|
||||
if(compact) {
|
||||
if(i && i%8 == 0)
|
||||
*sp++ = '-', *sp++ = '-';
|
||||
else if(i && i%4 == 0)
|
||||
*sp++ = '.';
|
||||
} else {
|
||||
if(cb == 'a') {
|
||||
sprintf(sp, "%d", op->bit[i].bitno);
|
||||
sp += strlen(sp);
|
||||
}
|
||||
if(i) {
|
||||
if(detailed)
|
||||
*sp++ = ' ';
|
||||
if(i%8 == 0)
|
||||
*sp++ = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
if(detailed)
|
||||
*sp++ = '"';
|
||||
*sp = 0;
|
||||
|
||||
return strdup(space);
|
||||
}
|
||||
|
||||
|
||||
// return 0 if op code would encode (essentially) the same SPI command
|
||||
static int opcodecmp(OPCODE *op1, OPCODE *op2, int opnum) {
|
||||
char *opstr1, *opstr2, *p;
|
||||
|
@ -215,19 +107,6 @@ static void printallopcodes(AVRPART *p, const char *d, OPCODE **opa) {
|
|||
}
|
||||
|
||||
|
||||
// returns position 0..31 of highest bit set or INT_MIN if no bit is set
|
||||
int intlog2(unsigned int n) {
|
||||
int ret;
|
||||
|
||||
if(!n)
|
||||
return INT_MIN;
|
||||
|
||||
for(ret = 0; n >>= 1; ret++)
|
||||
continue;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// mnemonic characterisation of flags
|
||||
static char *parttype(AVRPART *p) {
|
||||
|
@ -295,99 +174,6 @@ static void checkaddr(int memsize, int pagesize, int opnum, OPCODE *op, AVRPART
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* avr_set_addr_mem()
|
||||
*
|
||||
* Set address bits in the specified command based on the memory, opcode and
|
||||
* address; addr must be a word address for flash or, for all other memories,
|
||||
* a byte address; returns 0 on success and -1 on error (no memory or no
|
||||
* opcode) or, if positive, bn+1 where bn is bit number of the highest
|
||||
* necessary bit that the opcode does not provide.
|
||||
*/
|
||||
int avr_set_addr_mem(AVRMEM *mem, int opnum, unsigned char *cmd, unsigned long addr) {
|
||||
int ret, isflash, lo, hi, memsize, pagesize;
|
||||
OPCODE *op;
|
||||
|
||||
if(!mem)
|
||||
return -1;
|
||||
|
||||
if(!(op = mem->op[opnum]))
|
||||
return -1;
|
||||
|
||||
isflash = !strcmp(mem->desc, "flash"); // ISP parts have only one flash-like memory
|
||||
memsize = mem->size >> isflash; // word addresses for flash
|
||||
pagesize = mem->page_size >> isflash;
|
||||
|
||||
// compute range lo..hi of needed address bits
|
||||
switch(opnum) {
|
||||
case AVR_OP_READ:
|
||||
case AVR_OP_WRITE:
|
||||
case AVR_OP_READ_LO:
|
||||
case AVR_OP_READ_HI:
|
||||
case AVR_OP_WRITE_LO:
|
||||
case AVR_OP_WRITE_HI:
|
||||
lo = 0;
|
||||
hi = intlog2(memsize-1); // memsize = 1 implies no addr bit is needed
|
||||
break;
|
||||
|
||||
case AVR_OP_LOADPAGE_LO:
|
||||
case AVR_OP_LOADPAGE_HI:
|
||||
lo = 0;
|
||||
hi = intlog2(pagesize-1);
|
||||
break;
|
||||
|
||||
case AVR_OP_LOAD_EXT_ADDR:
|
||||
lo = 16;
|
||||
hi = intlog2(memsize-1);
|
||||
break;
|
||||
|
||||
case AVR_OP_WRITEPAGE:
|
||||
lo = intlog2(pagesize);
|
||||
hi = intlog2(memsize-1);
|
||||
break;
|
||||
|
||||
case AVR_OP_CHIP_ERASE:
|
||||
case AVR_OP_PGM_ENABLE:
|
||||
default:
|
||||
lo = 0;
|
||||
hi = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
// Unless it's load extended address, ISP chips only deal with 16 bit addresses
|
||||
if(opnum != AVR_OP_LOAD_EXT_ADDR && hi > 15)
|
||||
hi = 15;
|
||||
|
||||
unsigned char avail[32];
|
||||
memset(avail, 0, sizeof avail);
|
||||
|
||||
for(int i=0; i<32; i++) {
|
||||
if(op->bit[i].type == AVR_CMDBIT_ADDRESS) {
|
||||
int bitno, j, bit;
|
||||
unsigned char mask;
|
||||
|
||||
bitno = op->bit[i].bitno & 31;
|
||||
j = 3 - i / 8;
|
||||
bit = i % 8;
|
||||
mask = 1 << bit;
|
||||
avail[bitno] = 1;
|
||||
|
||||
// 'a' bit with number outside bit range [lo, hi] is set to 0
|
||||
if (bitno >= lo && bitno <= hi? (addr >> bitno) & 1: 0)
|
||||
cmd[j] = cmd[j] | mask;
|
||||
else
|
||||
cmd[j] = cmd[j] & ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
if(lo >= 0 && hi < 32 && lo <= hi)
|
||||
for(int bn=lo; bn <= hi; bn++)
|
||||
if(!avail[bn]) // necessary bit bn misses in opcode
|
||||
ret = bn+1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *dev_sprintf(const char *fmt, ...) {
|
||||
int size = 0;
|
||||
|
@ -841,126 +627,6 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) {
|
|||
|
||||
|
||||
|
||||
/*
|
||||
* Match STRING against the partname pattern PATTERN, returning 1 if it
|
||||
* matches, 0 if not. NOTE: part_match() is a modified old copy of !fnmatch()
|
||||
* from the GNU C Library (published under GLP v2). Used for portability.
|
||||
*/
|
||||
|
||||
inline static int fold(int c) {
|
||||
return (c >= 'A' && c <= 'Z')? c+('a'-'A'): c;
|
||||
}
|
||||
|
||||
int part_match(const char *pattern, const char *string) {
|
||||
unsigned char c;
|
||||
const char *p = pattern, *n = string;
|
||||
|
||||
if(!*n) // AVRDUDE specialty: empty string never matches
|
||||
return 0;
|
||||
|
||||
while((c = fold(*p++))) {
|
||||
switch(c) {
|
||||
case '?':
|
||||
if(*n == 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
c = fold(*p++);
|
||||
if(fold(*n) != c)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case '*':
|
||||
for(c = *p++; c == '?' || c == '*'; c = *p++)
|
||||
if(c == '?' && *n++ == 0)
|
||||
return 0;
|
||||
|
||||
if(c == 0)
|
||||
return 1;
|
||||
|
||||
{
|
||||
unsigned char c1 = fold(c == '\\'? *p : c); // This char
|
||||
|
||||
for(--p; *n; ++n) // Recursively check reminder of string for *
|
||||
if((c == '[' || fold(*n) == c1) && part_match(p, n) == 1)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case '[':
|
||||
{
|
||||
int negate;
|
||||
|
||||
if(*n == 0)
|
||||
return 0;
|
||||
|
||||
negate = (*p == '!' || *p == '^');
|
||||
if(negate)
|
||||
++p;
|
||||
|
||||
c = *p++;
|
||||
for(;;) {
|
||||
unsigned char cstart = c, cend = c;
|
||||
|
||||
if(c == '\\')
|
||||
cstart = cend = *p++;
|
||||
|
||||
cstart = cend = fold(cstart);
|
||||
|
||||
if(c == 0) // [ (unterminated)
|
||||
return 0;
|
||||
|
||||
c = *p++;
|
||||
c = fold(c);
|
||||
|
||||
if(c == '-' && *p != ']') {
|
||||
cend = *p++;
|
||||
if(cend == '\\')
|
||||
cend = *p++;
|
||||
if(cend == 0)
|
||||
return 0;
|
||||
cend = fold(cend);
|
||||
|
||||
c = *p++;
|
||||
}
|
||||
|
||||
if(fold(*n) >= cstart && fold(*n) <= cend)
|
||||
goto matched;
|
||||
|
||||
if(c == ']')
|
||||
break;
|
||||
}
|
||||
if(!negate)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
matched:;
|
||||
while(c != ']') { // Skip the rest of the [...] that already matched
|
||||
|
||||
if(c == 0) // [... (unterminated)
|
||||
return 0;
|
||||
|
||||
c = *p++;
|
||||
if(c == '\\') // XXX 1003.2d11 is unclear if this is right
|
||||
++p;
|
||||
}
|
||||
if(negate)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if(c != fold(*n))
|
||||
return 0;
|
||||
}
|
||||
|
||||
++n;
|
||||
}
|
||||
|
||||
return *n == 0;
|
||||
}
|
||||
|
||||
|
||||
// -p */[cdosw*]
|
||||
void dev_output_part_defs(char *partdesc) {
|
||||
|
|
Loading…
Reference in New Issue