Harden string processing during parsing in lexer.l, config_gram.y and otherwise
- Replace strdup(s) with cfg_strdup(funname, s) that exits on out of mem - Replace malloc(n) with cfg_malloc(funname, n) that exits on out of mem - Change multiline string scanning in lexer.l to avoid core dump - Remove global variables string_buf and string_bug_ptr - Ensure reading strings unescapes strings C-Style - Ensure writing strings escapes strings C-Style again Commit looks longer than needed as unescape() and auxiliary functions needed to be moved from term.c (not in libavrdude) to config.c (in libavrdude).
This commit is contained in:
parent
8a717987ec
commit
22c4dbf23e
|
@ -1243,7 +1243,7 @@ void avr_add_mem_order(const char *str) {
|
||||||
if(avr_mem_order[i] && !strcmp(avr_mem_order[i], str))
|
if(avr_mem_order[i] && !strcmp(avr_mem_order[i], str))
|
||||||
return;
|
return;
|
||||||
if(!avr_mem_order[i]) {
|
if(!avr_mem_order[i]) {
|
||||||
avr_mem_order[i] = strdup(str);
|
avr_mem_order[i] = cfg_strdup("avr_mem_order()", str);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -956,7 +956,7 @@ char *cmdbitstr(CMDBIT cb) {
|
||||||
else
|
else
|
||||||
space[1] = 0;
|
space[1] = 0;
|
||||||
|
|
||||||
return strdup(space);
|
return cfg_strdup("cmdbitstr()", space);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -998,7 +998,7 @@ char *opcode2str(OPCODE *op, int opnum, int detailed) {
|
||||||
int compact = 1;
|
int compact = 1;
|
||||||
|
|
||||||
if(!op)
|
if(!op)
|
||||||
return strdup("NULL");
|
return cfg_strdup("opcode2str()", "NULL");
|
||||||
|
|
||||||
// Can the opcode be printed in a compact way? Only if address bits are systematic.
|
// Can the opcode be printed in a compact way? Only if address bits are systematic.
|
||||||
for(int i=31; i >= 0; i--)
|
for(int i=31; i >= 0; i--)
|
||||||
|
@ -1033,7 +1033,7 @@ char *opcode2str(OPCODE *op, int opnum, int detailed) {
|
||||||
*sp++ = '"';
|
*sp++ = '"';
|
||||||
*sp = 0;
|
*sp = 0;
|
||||||
|
|
||||||
return strdup(space);
|
return cfg_strdup("opcode2str()", space);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
338
src/config.c
338
src/config.c
|
@ -25,6 +25,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "avrdude.h"
|
#include "avrdude.h"
|
||||||
#include "libavrdude.h"
|
#include "libavrdude.h"
|
||||||
|
@ -38,9 +39,6 @@ char default_serial[PATH_MAX];
|
||||||
char default_spi[PATH_MAX];
|
char default_spi[PATH_MAX];
|
||||||
double default_bitclock;
|
double default_bitclock;
|
||||||
|
|
||||||
char string_buf[MAX_STR_CONST];
|
|
||||||
char *string_buf_ptr;
|
|
||||||
|
|
||||||
LISTID string_list;
|
LISTID string_list;
|
||||||
LISTID number_list;
|
LISTID number_list;
|
||||||
PROGRAMMER * current_prog;
|
PROGRAMMER * current_prog;
|
||||||
|
@ -82,6 +80,25 @@ int init_config(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *cfg_malloc(const char *funcname, size_t n) {
|
||||||
|
void *ret = malloc(n);
|
||||||
|
if(!ret) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: out of memory in %s\n", progname, funcname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
memset(ret, 0, n);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *cfg_strdup(const char *funcname, const char *s) {
|
||||||
|
char *ret = strdup(s);
|
||||||
|
if(!ret) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: out of memory in %s\n", progname, funcname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int yywrap()
|
int yywrap()
|
||||||
|
@ -124,20 +141,9 @@ int yywarning(char * errmsg, ...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TOKEN * new_token(int primary)
|
TOKEN * new_token(int primary) {
|
||||||
{
|
TOKEN * tkn = (TOKEN *) cfg_malloc("new_token()", sizeof(TOKEN));
|
||||||
TOKEN * tkn;
|
|
||||||
|
|
||||||
tkn = (TOKEN *)malloc(sizeof(TOKEN));
|
|
||||||
if (tkn == NULL) {
|
|
||||||
yyerror("new_token(): out of memory");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(tkn, 0, sizeof(TOKEN));
|
|
||||||
|
|
||||||
tkn->primary = primary;
|
tkn->primary = primary;
|
||||||
|
|
||||||
return tkn;
|
return tkn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,14 +179,8 @@ void free_tokens(int n, ...)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TOKEN * number(char * text)
|
TOKEN *number(const char *text) {
|
||||||
{
|
struct token_t *tkn = new_token(TKN_NUMBER);
|
||||||
struct token_t * tkn;
|
|
||||||
|
|
||||||
tkn = new_token(TKN_NUMBER);
|
|
||||||
if (tkn == NULL) {
|
|
||||||
return NULL; /* yyerror already called */
|
|
||||||
}
|
|
||||||
tkn->value.type = V_NUM;
|
tkn->value.type = V_NUM;
|
||||||
tkn->value.number = atoi(text);
|
tkn->value.number = atoi(text);
|
||||||
|
|
||||||
|
@ -191,11 +191,8 @@ TOKEN * number(char * text)
|
||||||
return tkn;
|
return tkn;
|
||||||
}
|
}
|
||||||
|
|
||||||
TOKEN * number_real(char * text)
|
TOKEN *number_real(const char *text) {
|
||||||
{
|
struct token_t * tkn = new_token(TKN_NUMBER);
|
||||||
struct token_t * tkn;
|
|
||||||
|
|
||||||
tkn = new_token(TKN_NUMBER);
|
|
||||||
tkn->value.type = V_NUM_REAL;
|
tkn->value.type = V_NUM_REAL;
|
||||||
tkn->value.number_real = atof(text);
|
tkn->value.number_real = atof(text);
|
||||||
|
|
||||||
|
@ -206,15 +203,10 @@ TOKEN * number_real(char * text)
|
||||||
return tkn;
|
return tkn;
|
||||||
}
|
}
|
||||||
|
|
||||||
TOKEN * hexnumber(char * text)
|
TOKEN *hexnumber(const char *text) {
|
||||||
{
|
struct token_t *tkn = new_token(TKN_NUMBER);
|
||||||
struct token_t * tkn;
|
|
||||||
char * e;
|
char * e;
|
||||||
|
|
||||||
tkn = new_token(TKN_NUMBER);
|
|
||||||
if (tkn == NULL) {
|
|
||||||
return NULL; /* yyerror already called */
|
|
||||||
}
|
|
||||||
tkn->value.type = V_NUM;
|
tkn->value.type = V_NUM;
|
||||||
tkn->value.number = strtoul(text, &e, 16);
|
tkn->value.number = strtoul(text, &e, 16);
|
||||||
if ((e == text) || (*e != 0)) {
|
if ((e == text) || (*e != 0)) {
|
||||||
|
@ -231,26 +223,10 @@ TOKEN * hexnumber(char * text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TOKEN * string(char * text)
|
TOKEN *string(const char *text) {
|
||||||
{
|
struct token_t *tkn = new_token(TKN_STRING);
|
||||||
struct token_t * tkn;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
tkn = new_token(TKN_STRING);
|
|
||||||
if (tkn == NULL) {
|
|
||||||
return NULL; /* yyerror already called */
|
|
||||||
}
|
|
||||||
|
|
||||||
len = strlen(text);
|
|
||||||
|
|
||||||
tkn->value.type = V_STR;
|
tkn->value.type = V_STR;
|
||||||
tkn->value.string = (char *) malloc(len+1);
|
tkn->value.string = cfg_strdup("string()", text);
|
||||||
if (tkn->value.string == NULL) {
|
|
||||||
yyerror("string(): out of memory");
|
|
||||||
free_token(tkn);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
strcpy(tkn->value.string, text);
|
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
avrdude_message(MSG_INFO, "STRING(%s)\n", tkn->value.string);
|
avrdude_message(MSG_INFO, "STRING(%s)\n", tkn->value.string);
|
||||||
|
@ -260,13 +236,8 @@ TOKEN * string(char * text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TOKEN * keyword(int primary)
|
TOKEN * keyword(int primary) {
|
||||||
{
|
return new_token(primary);
|
||||||
struct token_t * tkn;
|
|
||||||
|
|
||||||
tkn = new_token(primary);
|
|
||||||
|
|
||||||
return tkn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -306,19 +277,6 @@ void pyytext(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char * dup_string(const char * str)
|
|
||||||
{
|
|
||||||
char * s;
|
|
||||||
|
|
||||||
s = strdup(str);
|
|
||||||
if (s == NULL) {
|
|
||||||
yyerror("dup_string(): out of memory");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_YYLEX_DESTROY
|
#ifdef HAVE_YYLEX_DESTROY
|
||||||
/* reset lexer and free any allocated memory */
|
/* reset lexer and free any allocated memory */
|
||||||
extern int yylex_destroy(void);
|
extern int yylex_destroy(void);
|
||||||
|
@ -386,11 +344,7 @@ const char *cache_string(const char *file) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fnames[n] = strdup(file);
|
fnames[n] = cfg_strdup("cache_string()", file);
|
||||||
if(!fnames[n]) {
|
|
||||||
yyerror("cache_string(): out of memory");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fnames[n++];
|
return fnames[n++];
|
||||||
}
|
}
|
||||||
|
@ -399,3 +353,227 @@ const char *cache_string(const char *file) {
|
||||||
int capture_comment_char(int c) {
|
int capture_comment_char(int c) {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Convert the next n hex digits of s to a hex number
|
||||||
|
static unsigned int tohex(const unsigned char *s, unsigned int n) {
|
||||||
|
int ret, c;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
while(n--) {
|
||||||
|
ret *= 16;
|
||||||
|
c = *s++;
|
||||||
|
ret += c >= '0' && c <= '9'? c - '0': c >= 'a' && c <= 'f'? c - 'a' + 10: c - 'A' + 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a utf-8 character sequence from a single unicode character.
|
||||||
|
* Permissive for some invalid unicode sequences but not for those with
|
||||||
|
* high bit set). Returns numbers of characters written (0-6).
|
||||||
|
*/
|
||||||
|
static int wc_to_utf8str(unsigned int wc, unsigned char *str) {
|
||||||
|
if(!(wc & ~0x7fu)) {
|
||||||
|
*str = (char) wc;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(!(wc & ~0x7ffu)) {
|
||||||
|
*str++ = (char) ((wc >> 6) | 0xc0);
|
||||||
|
*str++ = (char) ((wc & 0x3f) | 0x80);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if(!(wc & ~0xffffu)) {
|
||||||
|
*str++ = (char) ((wc >> 12) | 0xe0);
|
||||||
|
*str++ = (char) (((wc >> 6) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) ((wc & 0x3f) | 0x80);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if(!(wc & ~0x1fffffu)) {
|
||||||
|
*str++ = (char) ((wc >> 18) | 0xf0);
|
||||||
|
*str++ = (char) (((wc >> 12) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) (((wc >> 6) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) ((wc & 0x3f) | 0x80);
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
if(!(wc & ~0x3ffffffu)) {
|
||||||
|
*str++ = (char) ((wc >> 24) | 0xf8);
|
||||||
|
*str++ = (char) (((wc >> 18) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) (((wc >> 12) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) (((wc >> 6) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) ((wc & 0x3f) | 0x80);
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
if(!(wc & ~0x7fffffffu)) {
|
||||||
|
*str++ = (char) ((wc >> 30) | 0xfc);
|
||||||
|
*str++ = (char) (((wc >> 24) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) (((wc >> 18) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) (((wc >> 12) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) (((wc >> 6) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) ((wc & 0x3f) | 0x80);
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unescape C-style strings, destination d must hold enough space (and can be source s)
|
||||||
|
unsigned char *cfg_unescapeu(unsigned char *d, const unsigned char *s) {
|
||||||
|
unsigned char *ret = d;
|
||||||
|
int n, k;
|
||||||
|
|
||||||
|
while(*s) {
|
||||||
|
switch (*s) {
|
||||||
|
case '\\':
|
||||||
|
switch (*++s) {
|
||||||
|
case 'n':
|
||||||
|
*d = '\n';
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
*d = '\t';
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
*d = '\a';
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
*d = '\b';
|
||||||
|
break;
|
||||||
|
case 'e': // Non-standard ESC
|
||||||
|
*d = 27;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
*d = '\f';
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
*d = '\r';
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
*d = '\v';
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
*d = '?';
|
||||||
|
break;
|
||||||
|
case '`':
|
||||||
|
*d = '`';
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
*d = '"';
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
*d = '\'';
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
*d = '\\';
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7': // 1-3 octal digits
|
||||||
|
n = *s - '0';
|
||||||
|
for(k = 0; k < 2 && s[1] >= '0' && s[1] <= '7'; k++) // Max 2 more octal characters
|
||||||
|
n *= 8, n += s[1] - '0', s++;
|
||||||
|
*d = n;
|
||||||
|
break;
|
||||||
|
case 'x': // Unlimited hex digits
|
||||||
|
for(k = 0; isxdigit(s[k + 1]); k++)
|
||||||
|
continue;
|
||||||
|
if(k > 0) {
|
||||||
|
*d = tohex(s + 1, k);
|
||||||
|
s += k;
|
||||||
|
} else { // No hex digits after \x? copy \x
|
||||||
|
*d++ = '\\';
|
||||||
|
*d = 'x';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'u': // Exactly 4 hex digits and valid unicode
|
||||||
|
if(isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]) && isxdigit(s[4]) &&
|
||||||
|
(n = wc_to_utf8str(tohex(s+1, 4), d))) {
|
||||||
|
d += n - 1;
|
||||||
|
s += 4;
|
||||||
|
} else { // Invalid \u sequence? copy \u
|
||||||
|
*d++ = '\\';
|
||||||
|
*d = 'u';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'U': // Exactly 6 hex digits and valid unicode
|
||||||
|
if(isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]) && isxdigit(s[4]) && isxdigit(s[5]) && isxdigit(s[6]) &&
|
||||||
|
(n = wc_to_utf8str(tohex(s+1, 6), d))) {
|
||||||
|
d += n - 1;
|
||||||
|
s += 6;
|
||||||
|
} else { // Invalid \U sequence? copy \U
|
||||||
|
*d++ = '\\';
|
||||||
|
*d = 'U';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: // Keep the escape sequence (C would warn and remove \)
|
||||||
|
*d++ = '\\';
|
||||||
|
*d = *s;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: // Not an escape sequence: just copy the character
|
||||||
|
*d = *s;
|
||||||
|
}
|
||||||
|
d++;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
*d = *s; // Terminate
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unescape C-style strings, destination d must hold enough space (and can be source s)
|
||||||
|
char *cfg_unescape(char *d, const char *s) {
|
||||||
|
return (char *) cfg_unescapeu((unsigned char *) d, (const unsigned char *) s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return an escaped string that looks like a C-style input string incl quotes, memory is malloc()ed
|
||||||
|
char *cfg_escape(const char *s) {
|
||||||
|
char *ret = (char *) cfg_malloc("cfg_escape()", 4*strlen(s)+2+3), *d = ret;
|
||||||
|
|
||||||
|
*d++ = '"';
|
||||||
|
for(; *s; s++) {
|
||||||
|
switch(*s) {
|
||||||
|
case '\n':
|
||||||
|
*d++ = '\\'; *d++ = 'n';
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
*d++ = '\\'; *d++ = 't';
|
||||||
|
break;
|
||||||
|
case '\a':
|
||||||
|
*d++ = '\\'; *d++ = 'a';
|
||||||
|
break;
|
||||||
|
case '\b':
|
||||||
|
*d++ = '\\'; *d++ = 'b';
|
||||||
|
break;
|
||||||
|
case '\f':
|
||||||
|
*d++ = '\\'; *d++ = 'f';
|
||||||
|
break;
|
||||||
|
#if '\r' != '\n'
|
||||||
|
case '\r':
|
||||||
|
*d++ = '\\'; *d++ = 'r';
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case '\v':
|
||||||
|
*d++ = '\\'; *d++ = 'v';
|
||||||
|
break;
|
||||||
|
case '\"':
|
||||||
|
*d++ = '\\'; *d++ = '\"';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if(*s == 0x7f || (*s >= 0 && *s < 32)) {
|
||||||
|
sprintf(d, "\\%03o", *s);
|
||||||
|
d += strlen(d);
|
||||||
|
} else
|
||||||
|
*d++ = *s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*d++ = '"';
|
||||||
|
*d = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
29
src/config.h
29
src/config.h
|
@ -35,11 +35,11 @@
|
||||||
enum { V_NONE, V_NUM, V_NUM_REAL, V_STR };
|
enum { V_NONE, V_NUM, V_NUM_REAL, V_STR };
|
||||||
typedef struct value_t {
|
typedef struct value_t {
|
||||||
int type;
|
int type;
|
||||||
/*union { TODO: use an anonymous union here ? */
|
union {
|
||||||
int number;
|
int number;
|
||||||
double number_real;
|
double number_real;
|
||||||
char * string;
|
char * string;
|
||||||
/*};*/
|
};
|
||||||
} VALUE;
|
} VALUE;
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,41 +66,36 @@ extern bool is_alias; // current entry is alias
|
||||||
#endif
|
#endif
|
||||||
extern YYSTYPE yylval;
|
extern YYSTYPE yylval;
|
||||||
|
|
||||||
extern char string_buf[MAX_STR_CONST];
|
|
||||||
extern char *string_buf_ptr;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int yyparse(void);
|
int yyparse(void);
|
||||||
|
|
||||||
int yyerror(char * errmsg, ...);
|
int yyerror(char *errmsg, ...);
|
||||||
|
|
||||||
int yywarning(char * errmsg, ...);
|
int yywarning(char *errmsg, ...);
|
||||||
|
|
||||||
TOKEN * new_token(int primary);
|
TOKEN *new_token(int primary);
|
||||||
|
|
||||||
void free_token(TOKEN * tkn);
|
void free_token(TOKEN *tkn);
|
||||||
|
|
||||||
void free_tokens(int n, ...);
|
void free_tokens(int n, ...);
|
||||||
|
|
||||||
TOKEN * number(char * text);
|
TOKEN *number(const char *text);
|
||||||
|
|
||||||
TOKEN * number_real(char * text);
|
TOKEN *number_real(const char *text);
|
||||||
|
|
||||||
TOKEN * hexnumber(char * text);
|
TOKEN *hexnumber(const char *text);
|
||||||
|
|
||||||
TOKEN * string(char * text);
|
TOKEN *string(const char *text);
|
||||||
|
|
||||||
TOKEN * keyword(int primary);
|
TOKEN *keyword(int primary);
|
||||||
|
|
||||||
void print_token(TOKEN * tkn);
|
void print_token(TOKEN *tkn);
|
||||||
|
|
||||||
void pyytext(void);
|
void pyytext(void);
|
||||||
|
|
||||||
char * dup_string(const char * str);
|
|
||||||
|
|
||||||
int capture_comment_char(int c);
|
int capture_comment_char(int c);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -453,25 +453,11 @@ prog_parms :
|
||||||
prog_parm :
|
prog_parm :
|
||||||
K_ID TKN_EQUAL string_list {
|
K_ID TKN_EQUAL string_list {
|
||||||
{
|
{
|
||||||
TOKEN * t;
|
|
||||||
char *s;
|
|
||||||
int do_yyabort = 0;
|
|
||||||
while (lsize(string_list)) {
|
while (lsize(string_list)) {
|
||||||
t = lrmv_n(string_list, 1);
|
TOKEN *t = lrmv_n(string_list, 1);
|
||||||
if (!do_yyabort) {
|
ladd(current_prog->id, cfg_strdup("config_gram.y", t->value.string));
|
||||||
s = dup_string(t->value.string);
|
|
||||||
if (s == NULL) {
|
|
||||||
do_yyabort = 1;
|
|
||||||
} else {
|
|
||||||
ladd(current_prog->id, s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* if do_yyabort == 1 just make the list empty */
|
|
||||||
free_token(t);
|
free_token(t);
|
||||||
}
|
}
|
||||||
if (do_yyabort) {
|
|
||||||
YYABORT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} |
|
} |
|
||||||
prog_parm_type
|
prog_parm_type
|
||||||
|
|
|
@ -187,20 +187,17 @@ static char *dev_sprintf(const char *fmt, ...) {
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if(size < 0)
|
if(size < 0)
|
||||||
return NULL;
|
return cfg_strdup("dev_sprintf()", "");
|
||||||
|
|
||||||
size++; // For temrinating '\0'
|
size++; // For terminating '\0'
|
||||||
if(!(p = malloc(size)))
|
p = cfg_malloc("dev_sprintf()", size);
|
||||||
return NULL;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
size = vsnprintf(p, size, fmt, ap);
|
size = vsnprintf(p, size, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if(size < 0) {
|
if(size < 0)
|
||||||
free(p);
|
*p = 0;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -438,9 +435,10 @@ static void dev_part_raw(AVRPART *part) {
|
||||||
|
|
||||||
static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) {
|
static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) {
|
||||||
|
|
||||||
|
char *descstr = cfg_escape(p->desc);
|
||||||
if(!tsv) {
|
if(!tsv) {
|
||||||
dev_info("#------------------------------------------------------------\n");
|
dev_info("#------------------------------------------------------------\n");
|
||||||
dev_info("# %s\n", p->desc);
|
dev_info("# %.*s\n", strlen(descstr+1)-1, descstr+1);
|
||||||
dev_info("#------------------------------------------------------------\n");
|
dev_info("#------------------------------------------------------------\n");
|
||||||
if(p->parent_id && *p->parent_id)
|
if(p->parent_id && *p->parent_id)
|
||||||
dev_info("\npart parent \"%s\"\n", p->parent_id);
|
dev_info("\npart parent \"%s\"\n", p->parent_id);
|
||||||
|
@ -448,9 +446,9 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) {
|
||||||
dev_info("\npart\n");
|
dev_info("\npart\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
_if_partout(strcmp, "\"%s\"", desc);
|
_if_partout_str(strcmp, descstr, desc);
|
||||||
_if_partout(strcmp, "\"%s\"", id);
|
_if_partout_str(strcmp, cfg_escape(p->id), id);
|
||||||
_if_partout(strcmp, "\"%s\"", family_id);
|
_if_partout_str(strcmp, cfg_escape(p->family_id), family_id);
|
||||||
_if_partout(intcmp, "%d", hvupdi_variant);
|
_if_partout(intcmp, "%d", hvupdi_variant);
|
||||||
_if_partout(intcmp, "0x%02x", stk500_devcode);
|
_if_partout(intcmp, "0x%02x", stk500_devcode);
|
||||||
_if_partout(intcmp, "0x%02x", avr910_devcode);
|
_if_partout(intcmp, "0x%02x", avr910_devcode);
|
||||||
|
@ -461,9 +459,13 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) {
|
||||||
_if_partout(intcmp, "0x%04x", usbpid);
|
_if_partout(intcmp, "0x%04x", usbpid);
|
||||||
|
|
||||||
if(!base || base->reset_disposition != p->reset_disposition)
|
if(!base || base->reset_disposition != p->reset_disposition)
|
||||||
_partout_str(strdup(p->reset_disposition == RESET_DEDICATED? "dedicated": p->reset_disposition == RESET_IO? "io": "unknown"), reset);
|
_partout_str(cfg_strdup("dev_part_strct()",
|
||||||
|
p->reset_disposition == RESET_DEDICATED? "dedicated": p->reset_disposition == RESET_IO? "io": "unknown"),
|
||||||
|
reset);
|
||||||
|
|
||||||
_if_partout_str(intcmp, strdup(p->retry_pulse == PIN_AVR_RESET? "reset": p->retry_pulse == PIN_AVR_SCK? "sck": "unknown"), retry_pulse);
|
_if_partout_str(intcmp, cfg_strdup("dev_part_strct()",
|
||||||
|
p->retry_pulse == PIN_AVR_RESET? "reset": p->retry_pulse == PIN_AVR_SCK? "sck": "unknown"),
|
||||||
|
retry_pulse);
|
||||||
|
|
||||||
if(!base || base->flags != p->flags) {
|
if(!base || base->flags != p->flags) {
|
||||||
if(tsv) {
|
if(tsv) {
|
||||||
|
@ -482,7 +484,9 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) {
|
||||||
|
|
||||||
if(!base || (base->flags & (AVRPART_PARALLELOK | AVRPART_PSEUDOPARALLEL)) != (p->flags & (AVRPART_PARALLELOK | AVRPART_PSEUDOPARALLEL))) {
|
if(!base || (base->flags & (AVRPART_PARALLELOK | AVRPART_PSEUDOPARALLEL)) != (p->flags & (AVRPART_PARALLELOK | AVRPART_PSEUDOPARALLEL))) {
|
||||||
int par = p->flags & (AVRPART_PARALLELOK | AVRPART_PSEUDOPARALLEL);
|
int par = p->flags & (AVRPART_PARALLELOK | AVRPART_PSEUDOPARALLEL);
|
||||||
_partout_str(strdup(par == 0? "no": par == AVRPART_PSEUDOPARALLEL? "unknown": AVRPART_PARALLELOK? "yes": "pseudo"), parallel);
|
_partout_str(cfg_strdup("dev_part_strct()",
|
||||||
|
par == 0? "no": par == AVRPART_PSEUDOPARALLEL? "unknown": AVRPART_PARALLELOK? "yes": "pseudo"),
|
||||||
|
parallel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -984,13 +988,16 @@ static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) {
|
||||||
if(!firstid)
|
if(!firstid)
|
||||||
dev_info(", ");
|
dev_info(", ");
|
||||||
firstid = 0;
|
firstid = 0;
|
||||||
dev_info("\"%s\"", ldata(ln));
|
char *str = cfg_escape(ldata(ln));
|
||||||
|
dev_info("%s", str);
|
||||||
|
free(str);
|
||||||
}
|
}
|
||||||
dev_info(tsv? "\n": ";\n");
|
dev_info(tsv? "\n": ";\n");
|
||||||
|
|
||||||
_if_pgmout(strcmp, "\"%s\"", desc);
|
_if_pgmout_str(strcmp, cfg_escape(pgm->desc), desc);
|
||||||
_pgmout_fmt("type", "\"%s\"", locate_programmer_type_id(pgm->initpgm));
|
_pgmout_fmt("type", "\"%s\"", locate_programmer_type_id(pgm->initpgm));
|
||||||
_pgmout_fmt("connection_type", "%s", connstr(pgm->conntype));
|
if(!base || base->conntype != pgm->conntype)
|
||||||
|
_pgmout_fmt("connection_type", "%s", connstr(pgm->conntype));
|
||||||
_if_pgmout(intcmp, "%d", baudrate);
|
_if_pgmout(intcmp, "%d", baudrate);
|
||||||
|
|
||||||
_if_pgmout(intcmp, "0x%04x", usbvid);
|
_if_pgmout(intcmp, "0x%04x", usbvid);
|
||||||
|
@ -1009,10 +1016,10 @@ static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) {
|
||||||
dev_info(tsv? "\n": ";\n");
|
dev_info(tsv? "\n": ";\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
_if_pgmout(strcmp, "\"%s\"", usbdev);
|
_if_pgmout_str(strcmp, cfg_escape(pgm->usbdev), usbdev);
|
||||||
_if_pgmout(strcmp, "\"%s\"", usbsn);
|
_if_pgmout_str(strcmp, cfg_escape(pgm->usbsn), usbsn);
|
||||||
_if_pgmout(strcmp, "\"%s\"", usbvendor);
|
_if_pgmout_str(strcmp, cfg_escape(pgm->usbvendor), usbvendor);
|
||||||
_if_pgmout(strcmp, "\"%s\"", usbproduct);
|
_if_pgmout_str(strcmp, cfg_escape(pgm->usbproduct), usbproduct);
|
||||||
|
|
||||||
for(int i=0; i<N_PINS; i++) {
|
for(int i=0; i<N_PINS; i++) {
|
||||||
char *str = pins_to_strdup(pgm->pin+i);
|
char *str = pins_to_strdup(pgm->pin+i);
|
||||||
|
|
|
@ -62,6 +62,7 @@ static int dev_message(int msglvl, const char *fmt, ...);
|
||||||
dev_part_strct_entry(tsv, ".prog", id, NULL, #component, dev_sprintf(fmt, pgm->component)); \
|
dev_part_strct_entry(tsv, ".prog", id, NULL, #component, dev_sprintf(fmt, pgm->component)); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
// Result must be a malloc()ed string
|
||||||
#define _if_pgmout_str(cmp, result, component) do { \
|
#define _if_pgmout_str(cmp, result, component) do { \
|
||||||
if(!base || cmp(base->component, pgm->component)) \
|
if(!base || cmp(base->component, pgm->component)) \
|
||||||
dev_part_strct_entry(tsv, ".prog", id, NULL, #component, result); \
|
dev_part_strct_entry(tsv, ".prog", id, NULL, #component, result); \
|
||||||
|
@ -80,14 +81,17 @@ static int dev_message(int msglvl, const char *fmt, ...);
|
||||||
dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, dev_sprintf(fmt, p->component)); \
|
dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, dev_sprintf(fmt, p->component)); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
// Result must be a malloc()ed string
|
||||||
#define _partout_str(result, component) \
|
#define _partout_str(result, component) \
|
||||||
dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, result)
|
dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, result)
|
||||||
|
|
||||||
|
// Result must be a malloc()ed string
|
||||||
#define _if_partout_str(cmp, result, component) do { \
|
#define _if_partout_str(cmp, result, component) do { \
|
||||||
if(!base || cmp(base->component, p->component)) \
|
if(!base || cmp(base->component, p->component)) \
|
||||||
dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, result); \
|
dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, result); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
// Result must be a malloc()ed string
|
||||||
#define _if_n_partout_str(cmp, n, result, component) do { \
|
#define _if_n_partout_str(cmp, n, result, component) do { \
|
||||||
if(!base || cmp(base->component, p->component, n)) \
|
if(!base || cmp(base->component, p->component, n)) \
|
||||||
dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, result); \
|
dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, result); \
|
||||||
|
@ -102,30 +106,33 @@ static int dev_message(int msglvl, const char *fmt, ...);
|
||||||
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, dev_sprintf(fmt, m->component)); \
|
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, dev_sprintf(fmt, m->component)); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
// Result must be a malloc()ed string
|
||||||
#define _memout_str(result, component) \
|
#define _memout_str(result, component) \
|
||||||
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, result)
|
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, result)
|
||||||
|
|
||||||
|
// Result must be a malloc()ed string
|
||||||
#define _if_n_memout_str(cmp, n, result, component) do { \
|
#define _if_n_memout_str(cmp, n, result, component) do { \
|
||||||
if(!bm || cmp(bm->component, m->component, n)) \
|
if(!bm || cmp(bm->component, m->component, n)) \
|
||||||
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, result); \
|
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, result); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define _memout_yn(component) \
|
#define _memout_yn(component) \
|
||||||
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, strdup(m->component? "yes": "no"))
|
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, cfg_strdup("_memout_yn()", m->component? "yes": "no"))
|
||||||
|
|
||||||
#define _if_memout_yn(component) do { \
|
#define _if_memout_yn(component) do { \
|
||||||
if(!bm || bm->component != m->component) \
|
if(!bm || bm->component != m->component) \
|
||||||
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, strdup(m->component? "yes": "no")); \
|
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, cfg_strdup("_if_memout_yn()", m->component? "yes": "no")); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define _flagout(mask, name) \
|
#define _flagout(mask, name) \
|
||||||
_partout_str(strdup(p->flags & (mask)? "yes": "no"), name)
|
_partout_str(cfg_strdup("_flagout()", p->flags & (mask)? "yes": "no"), name)
|
||||||
|
|
||||||
#define _if_flagout(mask, name) do { \
|
#define _if_flagout(mask, name) do { \
|
||||||
if(!base || (base->flags & (mask)) != (p->flags & (mask))) \
|
if(!base || (base->flags & (mask)) != (p->flags & (mask))) \
|
||||||
_partout_str(strdup(p->flags & (mask)? "yes": "no"), name); \
|
_partout_str(cfg_strdup("_if_flagout()", p->flags & (mask)? "yes": "no"), name); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
// Result must be a malloc()ed string
|
||||||
#define _cmderr(result, component) \
|
#define _cmderr(result, component) \
|
||||||
dev_part_strct_entry(tsv, ".cmderr", p->desc, m->desc, #component, result)
|
dev_part_strct_entry(tsv, ".cmderr", p->desc, m->desc, #component, result)
|
||||||
|
|
||||||
|
|
28
src/lexer.l
28
src/lexer.l
|
@ -45,7 +45,6 @@ DIGIT [0-9]
|
||||||
HEXDIGIT [0-9a-fA-F]
|
HEXDIGIT [0-9a-fA-F]
|
||||||
SIGN [+-]
|
SIGN [+-]
|
||||||
|
|
||||||
%x strng
|
|
||||||
%x incl
|
%x incl
|
||||||
%x comment
|
%x comment
|
||||||
%option nounput
|
%option nounput
|
||||||
|
@ -61,12 +60,19 @@ SIGN [+-]
|
||||||
{SIGN}?{DIGIT}+"."{DIGIT}* { yylval = number_real(yytext); return TKN_NUMBER_REAL; }
|
{SIGN}?{DIGIT}+"."{DIGIT}* { yylval = number_real(yytext); return TKN_NUMBER_REAL; }
|
||||||
{SIGN}?"."{DIGIT}+ { yylval = number_real(yytext); return TKN_NUMBER_REAL; }
|
{SIGN}?"."{DIGIT}+ { yylval = number_real(yytext); return TKN_NUMBER_REAL; }
|
||||||
|
|
||||||
"\"" { string_buf_ptr = string_buf; BEGIN(strng); }
|
["]([^"\\\n]|\\.|\\\n)*["] {
|
||||||
|
char *str= cfg_strdup("lexer.l", yytext);
|
||||||
|
cfg_unescape(str, str+1);
|
||||||
|
size_t len = strlen(str);
|
||||||
|
if(len)
|
||||||
|
str[len-1] = 0;
|
||||||
|
yylval = string(str);
|
||||||
|
free(str);
|
||||||
|
return TKN_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
0x{HEXDIGIT}+ { yylval = hexnumber(yytext); return TKN_NUMBER; }
|
0x{HEXDIGIT}+ { yylval = hexnumber(yytext); return TKN_NUMBER; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# { /* The following captures all '#' style comments to end of line */
|
# { /* The following captures all '#' style comments to end of line */
|
||||||
BEGIN(comment); }
|
BEGIN(comment); }
|
||||||
<comment>[^\n]*\n+ { /* eat comments */
|
<comment>[^\n]*\n+ { /* eat comments */
|
||||||
|
@ -107,20 +113,6 @@ SIGN [+-]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
<strng>\" { *string_buf_ptr = 0; string_buf_ptr = string_buf;
|
|
||||||
yylval = string(string_buf_ptr); BEGIN(INITIAL); return TKN_STRING; }
|
|
||||||
<strng>\\n *string_buf_ptr++ = '\n';
|
|
||||||
<strng>\\t *string_buf_ptr++ = '\t';
|
|
||||||
<strng>\\r *string_buf_ptr++ = '\r';
|
|
||||||
<strng>\\b *string_buf_ptr++ = '\b';
|
|
||||||
<strng>\\f *string_buf_ptr++ = '\f';
|
|
||||||
<strng>\\(.|\n) *(string_buf_ptr++) = yytext[1];
|
|
||||||
<strng>[^\\\n\"]+ { char *yptr = yytext; while (*yptr)
|
|
||||||
*(string_buf_ptr++) = *(yptr++); }
|
|
||||||
|
|
||||||
<strng>\n { yyerror("unterminated character constant");
|
|
||||||
return YYERRCODE; }
|
|
||||||
|
|
||||||
alias { yylval=NULL; return K_ALIAS; }
|
alias { yylval=NULL; return K_ALIAS; }
|
||||||
allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; }
|
allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; }
|
||||||
avr910_devcode { yylval=NULL; return K_AVR910_DEVCODE; }
|
avr910_devcode { yylval=NULL; return K_AVR910_DEVCODE; }
|
||||||
|
|
|
@ -536,7 +536,7 @@ const char * pins_to_str(const struct pindef_t * const pindef);
|
||||||
* This function returns a string of defined pins, eg, ~1, 2, ~4, ~5, 7 or ""
|
* This function returns a string of defined pins, eg, ~1, 2, ~4, ~5, 7 or ""
|
||||||
*
|
*
|
||||||
* @param[in] pindef the pin definition for which we want the string representation
|
* @param[in] pindef the pin definition for which we want the string representation
|
||||||
* @returns a pointer to a string, which was created by strdup (NULL if out of memory)
|
* @returns a pointer to a string, which was created by strdup
|
||||||
*/
|
*/
|
||||||
char *pins_to_strdup(const struct pindef_t * const pindef);
|
char *pins_to_strdup(const struct pindef_t * const pindef);
|
||||||
|
|
||||||
|
@ -1006,6 +1006,10 @@ extern double default_bitclock;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void *cfg_malloc(const char *funcname, size_t n);
|
||||||
|
|
||||||
|
char *cfg_strdup(const char *funcname, const char *s);
|
||||||
|
|
||||||
int init_config(void);
|
int init_config(void);
|
||||||
|
|
||||||
void cleanup_config(void);
|
void cleanup_config(void);
|
||||||
|
@ -1014,6 +1018,12 @@ int read_config(const char * file);
|
||||||
|
|
||||||
const char *cache_string(const char *file);
|
const char *cache_string(const char *file);
|
||||||
|
|
||||||
|
unsigned char *cfg_unescapeu(unsigned char *d, const unsigned char *s);
|
||||||
|
|
||||||
|
char *cfg_unescape(char *d, const char *s);
|
||||||
|
|
||||||
|
char *cfg_escape(const char *s);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -922,10 +922,7 @@ int main(int argc, char * argv [])
|
||||||
progname,
|
progname,
|
||||||
(upd->op == DEVICE_READ)? 'r': (upd->op == DEVICE_WRITE)? 'w': 'v',
|
(upd->op == DEVICE_READ)? 'r': (upd->op == DEVICE_WRITE)? 'w': 'v',
|
||||||
upd->filename, mtype);
|
upd->filename, mtype);
|
||||||
if ((upd->memtype = strdup(mtype)) == NULL) {
|
upd->memtype = cfg_strdup("main()", mtype);
|
||||||
avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!avr_mem_might_be_known(upd->memtype)) {
|
if (!avr_mem_might_be_known(upd->memtype)) {
|
||||||
|
|
24
src/pgm.c
24
src/pgm.c
|
@ -67,14 +67,7 @@ PROGRAMMER * pgm_new(void)
|
||||||
PROGRAMMER * pgm;
|
PROGRAMMER * pgm;
|
||||||
const char *nulp = cache_string("");
|
const char *nulp = cache_string("");
|
||||||
|
|
||||||
pgm = (PROGRAMMER *)malloc(sizeof(*pgm));
|
pgm = (PROGRAMMER *) cfg_malloc("pgm_new()", sizeof(*pgm));
|
||||||
if (pgm == NULL) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: out of memory allocating programmer structure\n",
|
|
||||||
progname);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(pgm, 0, sizeof(*pgm));
|
|
||||||
|
|
||||||
pgm->id = lcreat(NULL, 0);
|
pgm->id = lcreat(NULL, 0);
|
||||||
pgm->usbpid = lcreat(NULL, 0);
|
pgm->usbpid = lcreat(NULL, 0);
|
||||||
|
@ -162,24 +155,13 @@ PROGRAMMER * pgm_dup(const PROGRAMMER * const src)
|
||||||
PROGRAMMER * pgm;
|
PROGRAMMER * pgm;
|
||||||
LNODEID ln;
|
LNODEID ln;
|
||||||
|
|
||||||
pgm = (PROGRAMMER *)malloc(sizeof(*pgm));
|
pgm = (PROGRAMMER *) cfg_malloc("pgm_dup()", sizeof(*pgm));
|
||||||
if (pgm == NULL) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: out of memory allocating programmer structure\n",
|
|
||||||
progname);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(pgm, src, sizeof(*pgm));
|
memcpy(pgm, src, sizeof(*pgm));
|
||||||
|
|
||||||
pgm->id = lcreat(NULL, 0);
|
pgm->id = lcreat(NULL, 0);
|
||||||
pgm->usbpid = lcreat(NULL, 0);
|
pgm->usbpid = lcreat(NULL, 0);
|
||||||
for (ln = lfirst(src->usbpid); ln; ln = lnext(ln)) {
|
for (ln = lfirst(src->usbpid); ln; ln = lnext(ln)) {
|
||||||
int *ip = malloc(sizeof(int));
|
int *ip = cfg_malloc("pgm_dup()", sizeof(int));
|
||||||
if (ip == NULL) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: out of memory allocating programmer structure\n",
|
|
||||||
progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
*ip = *(int *) ldata(ln);
|
*ip = *(int *) ldata(ln);
|
||||||
ladd(pgm->usbpid, ip);
|
ladd(pgm->usbpid, ip);
|
||||||
}
|
}
|
||||||
|
|
|
@ -350,7 +350,7 @@ const char * pins_to_str(const struct pindef_t * const pindef) {
|
||||||
* This function returns a string of defined pins, eg, ~1, 2, ~4, ~5, 7 or ""
|
* This function returns a string of defined pins, eg, ~1, 2, ~4, ~5, 7 or ""
|
||||||
*
|
*
|
||||||
* @param[in] pindef the pin definition for which we want the string representation
|
* @param[in] pindef the pin definition for which we want the string representation
|
||||||
* @returns a pointer to a string, which was created by strdup (NULL if out of memory)
|
* @returns a pointer to a string, which was created by strdup
|
||||||
*/
|
*/
|
||||||
char *pins_to_strdup(const struct pindef_t * const pindef) {
|
char *pins_to_strdup(const struct pindef_t * const pindef) {
|
||||||
char buf[6*(PIN_MAX+1)], *p = buf;
|
char buf[6*(PIN_MAX+1)], *p = buf;
|
||||||
|
@ -365,7 +365,7 @@ char *pins_to_strdup(const struct pindef_t * const pindef) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return strdup(buf);
|
return cfg_strdup("pins_to_strdup()", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
175
src/term.c
175
src/term.c
|
@ -20,7 +20,6 @@
|
||||||
|
|
||||||
#include "ac_cfg.h"
|
#include "ac_cfg.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -346,178 +345,6 @@ static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Convert the next n hex digits of s to a hex number
|
|
||||||
static unsigned int tohex(const unsigned char *s, unsigned int n) {
|
|
||||||
int ret, c;
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
while(n--) {
|
|
||||||
ret *= 16;
|
|
||||||
c = *s++;
|
|
||||||
ret += c >= '0' && c <= '9'? c - '0': c >= 'a' && c <= 'f'? c - 'a' + 10: c - 'A' + 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a utf-8 character sequence from a single unicode character.
|
|
||||||
* Permissive for some invalid unicode sequences but not for those with
|
|
||||||
* high bit set). Returns numbers of characters written (0-6).
|
|
||||||
*/
|
|
||||||
static int wc_to_utf8str(unsigned int wc, unsigned char *str) {
|
|
||||||
if(!(wc & ~0x7fu)) {
|
|
||||||
*str = (char) wc;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if(!(wc & ~0x7ffu)) {
|
|
||||||
*str++ = (char) ((wc >> 6) | 0xc0);
|
|
||||||
*str++ = (char) ((wc & 0x3f) | 0x80);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
if(!(wc & ~0xffffu)) {
|
|
||||||
*str++ = (char) ((wc >> 12) | 0xe0);
|
|
||||||
*str++ = (char) (((wc >> 6) & 0x3f) | 0x80);
|
|
||||||
*str++ = (char) ((wc & 0x3f) | 0x80);
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
if(!(wc & ~0x1fffffu)) {
|
|
||||||
*str++ = (char) ((wc >> 18) | 0xf0);
|
|
||||||
*str++ = (char) (((wc >> 12) & 0x3f) | 0x80);
|
|
||||||
*str++ = (char) (((wc >> 6) & 0x3f) | 0x80);
|
|
||||||
*str++ = (char) ((wc & 0x3f) | 0x80);
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
if(!(wc & ~0x3ffffffu)) {
|
|
||||||
*str++ = (char) ((wc >> 24) | 0xf8);
|
|
||||||
*str++ = (char) (((wc >> 18) & 0x3f) | 0x80);
|
|
||||||
*str++ = (char) (((wc >> 12) & 0x3f) | 0x80);
|
|
||||||
*str++ = (char) (((wc >> 6) & 0x3f) | 0x80);
|
|
||||||
*str++ = (char) ((wc & 0x3f) | 0x80);
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
if(!(wc & ~0x7fffffffu)) {
|
|
||||||
*str++ = (char) ((wc >> 30) | 0xfc);
|
|
||||||
*str++ = (char) (((wc >> 24) & 0x3f) | 0x80);
|
|
||||||
*str++ = (char) (((wc >> 18) & 0x3f) | 0x80);
|
|
||||||
*str++ = (char) (((wc >> 12) & 0x3f) | 0x80);
|
|
||||||
*str++ = (char) (((wc >> 6) & 0x3f) | 0x80);
|
|
||||||
*str++ = (char) ((wc & 0x3f) | 0x80);
|
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unescape C-style strings, destination d must hold enough space (and can be source s)
|
|
||||||
static unsigned char *unescape(unsigned char *d, const unsigned char *s) {
|
|
||||||
unsigned char *ret = d;
|
|
||||||
int n, k;
|
|
||||||
|
|
||||||
while(*s) {
|
|
||||||
switch (*s) {
|
|
||||||
case '\\':
|
|
||||||
switch (*++s) {
|
|
||||||
case 'n':
|
|
||||||
*d = '\n';
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
*d = '\t';
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
*d = '\a';
|
|
||||||
break;
|
|
||||||
case 'b':
|
|
||||||
*d = '\b';
|
|
||||||
break;
|
|
||||||
case 'e': // Non-standard ESC
|
|
||||||
*d = 27;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
*d = '\f';
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
*d = '\r';
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
*d = '\v';
|
|
||||||
break;
|
|
||||||
case '?':
|
|
||||||
*d = '?';
|
|
||||||
break;
|
|
||||||
case '`':
|
|
||||||
*d = '`';
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
*d = '"';
|
|
||||||
break;
|
|
||||||
case '\'':
|
|
||||||
*d = '\'';
|
|
||||||
break;
|
|
||||||
case '\\':
|
|
||||||
*d = '\\';
|
|
||||||
break;
|
|
||||||
case '0':
|
|
||||||
case '1':
|
|
||||||
case '2':
|
|
||||||
case '3':
|
|
||||||
case '4':
|
|
||||||
case '5':
|
|
||||||
case '6':
|
|
||||||
case '7': // 1-3 octal digits
|
|
||||||
n = *s - '0';
|
|
||||||
for(k = 0; k < 2 && s[1] >= '0' && s[1] <= '7'; k++) // Max 2 more octal characters
|
|
||||||
n *= 8, n += s[1] - '0', s++;
|
|
||||||
*d = n;
|
|
||||||
break;
|
|
||||||
case 'x': // Unlimited hex digits
|
|
||||||
for(k = 0; isxdigit(s[k + 1]); k++)
|
|
||||||
continue;
|
|
||||||
if(k > 0) {
|
|
||||||
*d = tohex(s + 1, k);
|
|
||||||
s += k;
|
|
||||||
} else { // No hex digits after \x? copy \x
|
|
||||||
*d++ = '\\';
|
|
||||||
*d = 'x';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'u': // Exactly 4 hex digits and valid unicode
|
|
||||||
if(isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]) && isxdigit(s[4]) &&
|
|
||||||
(n = wc_to_utf8str(tohex(s+1, 4), d))) {
|
|
||||||
d += n - 1;
|
|
||||||
s += 4;
|
|
||||||
} else { // Invalid \u sequence? copy \u
|
|
||||||
*d++ = '\\';
|
|
||||||
*d = 'u';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'U': // Exactly 6 hex digits and valid unicode
|
|
||||||
if(isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]) && isxdigit(s[4]) && isxdigit(s[5]) && isxdigit(s[6]) &&
|
|
||||||
(n = wc_to_utf8str(tohex(s+1, 6), d))) {
|
|
||||||
d += n - 1;
|
|
||||||
s += 6;
|
|
||||||
} else { // Invalid \U sequence? copy \U
|
|
||||||
*d++ = '\\';
|
|
||||||
*d = 'U';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default: // Keep the escape sequence (C would warn and remove \)
|
|
||||||
*d++ = '\\';
|
|
||||||
*d = *s;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: // Not an escape sequence: just copy the character
|
|
||||||
*d = *s;
|
|
||||||
}
|
|
||||||
d++;
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
*d = *s; // Terminate
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static size_t maxstrlen(int argc, char **argv) {
|
static size_t maxstrlen(int argc, char **argv) {
|
||||||
size_t max = 0;
|
size_t max = 0;
|
||||||
|
|
||||||
|
@ -800,7 +627,7 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
|
||||||
}
|
}
|
||||||
// Strip start and end quotes, and unescape C string
|
// Strip start and end quotes, and unescape C string
|
||||||
strncpy(s, argi+1, arglen-2);
|
strncpy(s, argi+1, arglen-2);
|
||||||
unescape((unsigned char *) s, (unsigned char *) s);
|
cfg_unescape(s, s);
|
||||||
if (*argi == '\'') { // Single C-style character
|
if (*argi == '\'') { // Single C-style character
|
||||||
if(*s && s[1])
|
if(*s && s[1])
|
||||||
terminal_message(MSG_INFO, "%s (write): only using first character of %s\n",
|
terminal_message(MSG_INFO, "%s (write): only using first character of %s\n",
|
||||||
|
|
50
src/update.c
50
src/update.c
|
@ -37,11 +37,7 @@ UPDATE * parse_op(char * s)
|
||||||
int i;
|
int i;
|
||||||
size_t fnlen;
|
size_t fnlen;
|
||||||
|
|
||||||
upd = (UPDATE *)malloc(sizeof(UPDATE));
|
upd = (UPDATE *) cfg_malloc("parse_op()", sizeof(UPDATE));
|
||||||
if (upd == NULL) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
p = s;
|
p = s;
|
||||||
|
@ -52,22 +48,12 @@ UPDATE * parse_op(char * s)
|
||||||
if (*p != ':') {
|
if (*p != ':') {
|
||||||
upd->memtype = NULL; /* default memtype, "flash", or "application" */
|
upd->memtype = NULL; /* default memtype, "flash", or "application" */
|
||||||
upd->op = DEVICE_WRITE;
|
upd->op = DEVICE_WRITE;
|
||||||
upd->filename = (char *)malloc(strlen(buf) + 1);
|
upd->filename = cfg_strdup("parse_op()", buf);
|
||||||
if (upd->filename == NULL) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
strcpy(upd->filename, buf);
|
|
||||||
upd->format = FMT_AUTO;
|
upd->format = FMT_AUTO;
|
||||||
return upd;
|
return upd;
|
||||||
}
|
}
|
||||||
|
|
||||||
upd->memtype = (char *)malloc(strlen(buf)+1);
|
upd->memtype = cfg_strdup("parse_op()", buf);
|
||||||
if (upd->memtype == NULL) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
strcpy(upd->memtype, buf);
|
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
if (*p == 'r') {
|
if (*p == 'r') {
|
||||||
|
@ -118,10 +104,10 @@ UPDATE * parse_op(char * s)
|
||||||
// and to binary for read operations:
|
// and to binary for read operations:
|
||||||
upd->format = upd->op == DEVICE_READ? FMT_RBIN: FMT_AUTO;
|
upd->format = upd->op == DEVICE_READ? FMT_RBIN: FMT_AUTO;
|
||||||
fnlen = strlen(cp);
|
fnlen = strlen(cp);
|
||||||
upd->filename = (char *)malloc(fnlen + 1);
|
upd->filename = (char *) cfg_malloc("parse_op()", fnlen + 1);
|
||||||
} else {
|
} else {
|
||||||
fnlen = p - cp;
|
fnlen = p - cp;
|
||||||
upd->filename = (char *)malloc(fnlen +1);
|
upd->filename = (char *) cfg_malloc("parse_op()", fnlen +1);
|
||||||
c = *++p;
|
c = *++p;
|
||||||
if (c && p[1])
|
if (c && p[1])
|
||||||
/* More than one char - force failure below. */
|
/* More than one char - force failure below. */
|
||||||
|
@ -147,12 +133,6 @@ UPDATE * parse_op(char * s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (upd->filename == NULL) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
|
|
||||||
free(upd->memtype);
|
|
||||||
free(upd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memcpy(upd->filename, cp, fnlen);
|
memcpy(upd->filename, cp, fnlen);
|
||||||
upd->filename[fnlen] = 0;
|
upd->filename[fnlen] = 0;
|
||||||
|
|
||||||
|
@ -163,19 +143,15 @@ UPDATE * dup_update(UPDATE * upd)
|
||||||
{
|
{
|
||||||
UPDATE * u;
|
UPDATE * u;
|
||||||
|
|
||||||
u = (UPDATE *)malloc(sizeof(UPDATE));
|
u = (UPDATE *) cfg_malloc("dup_update()", sizeof(UPDATE));
|
||||||
if (u == NULL) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(u, upd, sizeof(UPDATE));
|
memcpy(u, upd, sizeof(UPDATE));
|
||||||
|
|
||||||
if (upd->memtype != NULL)
|
if (upd->memtype != NULL)
|
||||||
u->memtype = strdup(upd->memtype);
|
u->memtype = cfg_strdup("dup_update()", upd->memtype);
|
||||||
else
|
else
|
||||||
u->memtype = NULL;
|
u->memtype = NULL;
|
||||||
u->filename = strdup(upd->filename);
|
u->filename = cfg_strdup("dup_update()", upd->filename);
|
||||||
|
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
@ -184,14 +160,10 @@ UPDATE * new_update(int op, char * memtype, int filefmt, char * filename)
|
||||||
{
|
{
|
||||||
UPDATE * u;
|
UPDATE * u;
|
||||||
|
|
||||||
u = (UPDATE *)malloc(sizeof(UPDATE));
|
u = (UPDATE *) cfg_malloc("new_update()", sizeof(UPDATE));
|
||||||
if (u == NULL) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
u->memtype = strdup(memtype);
|
u->memtype = cfg_strdup("new_update()", memtype);
|
||||||
u->filename = strdup(filename);
|
u->filename = cfg_strdup("new_update()", filename);
|
||||||
u->op = op;
|
u->op = op;
|
||||||
u->format = filefmt;
|
u->format = filefmt;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue