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))
|
||||
return;
|
||||
if(!avr_mem_order[i]) {
|
||||
avr_mem_order[i] = strdup(str);
|
||||
avr_mem_order[i] = cfg_strdup("avr_mem_order()", str);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -956,7 +956,7 @@ char *cmdbitstr(CMDBIT cb) {
|
|||
else
|
||||
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;
|
||||
|
||||
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.
|
||||
for(int i=31; i >= 0; i--)
|
||||
|
@ -1033,7 +1033,7 @@ char *opcode2str(OPCODE *op, int opnum, int detailed) {
|
|||
*sp++ = '"';
|
||||
*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 <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "avrdude.h"
|
||||
#include "libavrdude.h"
|
||||
|
@ -38,9 +39,6 @@ char default_serial[PATH_MAX];
|
|||
char default_spi[PATH_MAX];
|
||||
double default_bitclock;
|
||||
|
||||
char string_buf[MAX_STR_CONST];
|
||||
char *string_buf_ptr;
|
||||
|
||||
LISTID string_list;
|
||||
LISTID number_list;
|
||||
PROGRAMMER * current_prog;
|
||||
|
@ -82,6 +80,25 @@ int init_config(void)
|
|||
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()
|
||||
|
@ -124,20 +141,9 @@ int yywarning(char * errmsg, ...)
|
|||
}
|
||||
|
||||
|
||||
TOKEN * new_token(int primary)
|
||||
{
|
||||
TOKEN * tkn;
|
||||
|
||||
tkn = (TOKEN *)malloc(sizeof(TOKEN));
|
||||
if (tkn == NULL) {
|
||||
yyerror("new_token(): out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(tkn, 0, sizeof(TOKEN));
|
||||
|
||||
TOKEN * new_token(int primary) {
|
||||
TOKEN * tkn = (TOKEN *) cfg_malloc("new_token()", sizeof(TOKEN));
|
||||
tkn->primary = primary;
|
||||
|
||||
return tkn;
|
||||
}
|
||||
|
||||
|
@ -173,14 +179,8 @@ void free_tokens(int n, ...)
|
|||
|
||||
|
||||
|
||||
TOKEN * number(char * text)
|
||||
{
|
||||
struct token_t * tkn;
|
||||
|
||||
tkn = new_token(TKN_NUMBER);
|
||||
if (tkn == NULL) {
|
||||
return NULL; /* yyerror already called */
|
||||
}
|
||||
TOKEN *number(const char *text) {
|
||||
struct token_t *tkn = new_token(TKN_NUMBER);
|
||||
tkn->value.type = V_NUM;
|
||||
tkn->value.number = atoi(text);
|
||||
|
||||
|
@ -191,11 +191,8 @@ TOKEN * number(char * text)
|
|||
return tkn;
|
||||
}
|
||||
|
||||
TOKEN * number_real(char * text)
|
||||
{
|
||||
struct token_t * tkn;
|
||||
|
||||
tkn = new_token(TKN_NUMBER);
|
||||
TOKEN *number_real(const char *text) {
|
||||
struct token_t * tkn = new_token(TKN_NUMBER);
|
||||
tkn->value.type = V_NUM_REAL;
|
||||
tkn->value.number_real = atof(text);
|
||||
|
||||
|
@ -206,15 +203,10 @@ TOKEN * number_real(char * text)
|
|||
return tkn;
|
||||
}
|
||||
|
||||
TOKEN * hexnumber(char * text)
|
||||
{
|
||||
struct token_t * tkn;
|
||||
TOKEN *hexnumber(const char *text) {
|
||||
struct token_t *tkn = new_token(TKN_NUMBER);
|
||||
char * e;
|
||||
|
||||
tkn = new_token(TKN_NUMBER);
|
||||
if (tkn == NULL) {
|
||||
return NULL; /* yyerror already called */
|
||||
}
|
||||
tkn->value.type = V_NUM;
|
||||
tkn->value.number = strtoul(text, &e, 16);
|
||||
if ((e == text) || (*e != 0)) {
|
||||
|
@ -231,26 +223,10 @@ TOKEN * hexnumber(char * text)
|
|||
}
|
||||
|
||||
|
||||
TOKEN * string(char * text)
|
||||
{
|
||||
struct token_t * tkn;
|
||||
int len;
|
||||
|
||||
tkn = new_token(TKN_STRING);
|
||||
if (tkn == NULL) {
|
||||
return NULL; /* yyerror already called */
|
||||
}
|
||||
|
||||
len = strlen(text);
|
||||
|
||||
TOKEN *string(const char *text) {
|
||||
struct token_t *tkn = new_token(TKN_STRING);
|
||||
tkn->value.type = V_STR;
|
||||
tkn->value.string = (char *) malloc(len+1);
|
||||
if (tkn->value.string == NULL) {
|
||||
yyerror("string(): out of memory");
|
||||
free_token(tkn);
|
||||
return NULL;
|
||||
}
|
||||
strcpy(tkn->value.string, text);
|
||||
tkn->value.string = cfg_strdup("string()", text);
|
||||
|
||||
#if DEBUG
|
||||
avrdude_message(MSG_INFO, "STRING(%s)\n", tkn->value.string);
|
||||
|
@ -260,13 +236,8 @@ TOKEN * string(char * text)
|
|||
}
|
||||
|
||||
|
||||
TOKEN * keyword(int primary)
|
||||
{
|
||||
struct token_t * tkn;
|
||||
|
||||
tkn = new_token(primary);
|
||||
|
||||
return tkn;
|
||||
TOKEN * keyword(int primary) {
|
||||
return new_token(primary);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
/* reset lexer and free any allocated memory */
|
||||
extern int yylex_destroy(void);
|
||||
|
@ -386,11 +344,7 @@ const char *cache_string(const char *file) {
|
|||
}
|
||||
}
|
||||
|
||||
fnames[n] = strdup(file);
|
||||
if(!fnames[n]) {
|
||||
yyerror("cache_string(): out of memory");
|
||||
return NULL;
|
||||
}
|
||||
fnames[n] = cfg_strdup("cache_string()", file);
|
||||
|
||||
return fnames[n++];
|
||||
}
|
||||
|
@ -399,3 +353,227 @@ const char *cache_string(const char *file) {
|
|||
int capture_comment_char(int 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;
|
||||
}
|
||||
|
|
17
src/config.h
17
src/config.h
|
@ -35,11 +35,11 @@
|
|||
enum { V_NONE, V_NUM, V_NUM_REAL, V_STR };
|
||||
typedef struct value_t {
|
||||
int type;
|
||||
/*union { TODO: use an anonymous union here ? */
|
||||
union {
|
||||
int number;
|
||||
double number_real;
|
||||
char * string;
|
||||
/*};*/
|
||||
};
|
||||
} VALUE;
|
||||
|
||||
|
||||
|
@ -66,9 +66,6 @@ extern bool is_alias; // current entry is alias
|
|||
#endif
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
extern char string_buf[MAX_STR_CONST];
|
||||
extern char *string_buf_ptr;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -85,13 +82,13 @@ void free_token(TOKEN * tkn);
|
|||
|
||||
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);
|
||||
|
||||
|
@ -99,8 +96,6 @@ void print_token(TOKEN * tkn);
|
|||
|
||||
void pyytext(void);
|
||||
|
||||
char * dup_string(const char * str);
|
||||
|
||||
int capture_comment_char(int c);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -453,25 +453,11 @@ prog_parms :
|
|||
prog_parm :
|
||||
K_ID TKN_EQUAL string_list {
|
||||
{
|
||||
TOKEN * t;
|
||||
char *s;
|
||||
int do_yyabort = 0;
|
||||
while (lsize(string_list)) {
|
||||
t = lrmv_n(string_list, 1);
|
||||
if (!do_yyabort) {
|
||||
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 */
|
||||
TOKEN *t = lrmv_n(string_list, 1);
|
||||
ladd(current_prog->id, cfg_strdup("config_gram.y", t->value.string));
|
||||
free_token(t);
|
||||
}
|
||||
if (do_yyabort) {
|
||||
YYABORT;
|
||||
}
|
||||
}
|
||||
} |
|
||||
prog_parm_type
|
||||
|
|
|
@ -187,20 +187,17 @@ static char *dev_sprintf(const char *fmt, ...) {
|
|||
va_end(ap);
|
||||
|
||||
if(size < 0)
|
||||
return NULL;
|
||||
return cfg_strdup("dev_sprintf()", "");
|
||||
|
||||
size++; // For temrinating '\0'
|
||||
if(!(p = malloc(size)))
|
||||
return NULL;
|
||||
size++; // For terminating '\0'
|
||||
p = cfg_malloc("dev_sprintf()", size);
|
||||
|
||||
va_start(ap, fmt);
|
||||
size = vsnprintf(p, size, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if(size < 0) {
|
||||
free(p);
|
||||
return NULL;
|
||||
}
|
||||
if(size < 0)
|
||||
*p = 0;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
@ -438,9 +435,10 @@ static void dev_part_raw(AVRPART *part) {
|
|||
|
||||
static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) {
|
||||
|
||||
char *descstr = cfg_escape(p->desc);
|
||||
if(!tsv) {
|
||||
dev_info("#------------------------------------------------------------\n");
|
||||
dev_info("# %s\n", p->desc);
|
||||
dev_info("# %.*s\n", strlen(descstr+1)-1, descstr+1);
|
||||
dev_info("#------------------------------------------------------------\n");
|
||||
if(p->parent_id && *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");
|
||||
}
|
||||
|
||||
_if_partout(strcmp, "\"%s\"", desc);
|
||||
_if_partout(strcmp, "\"%s\"", id);
|
||||
_if_partout(strcmp, "\"%s\"", family_id);
|
||||
_if_partout_str(strcmp, descstr, desc);
|
||||
_if_partout_str(strcmp, cfg_escape(p->id), id);
|
||||
_if_partout_str(strcmp, cfg_escape(p->family_id), family_id);
|
||||
_if_partout(intcmp, "%d", hvupdi_variant);
|
||||
_if_partout(intcmp, "0x%02x", stk500_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(!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(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))) {
|
||||
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,12 +988,15 @@ static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) {
|
|||
if(!firstid)
|
||||
dev_info(", ");
|
||||
firstid = 0;
|
||||
dev_info("\"%s\"", ldata(ln));
|
||||
char *str = cfg_escape(ldata(ln));
|
||||
dev_info("%s", str);
|
||||
free(str);
|
||||
}
|
||||
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));
|
||||
if(!base || base->conntype != pgm->conntype)
|
||||
_pgmout_fmt("connection_type", "%s", connstr(pgm->conntype));
|
||||
_if_pgmout(intcmp, "%d", baudrate);
|
||||
|
||||
|
@ -1009,10 +1016,10 @@ static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) {
|
|||
dev_info(tsv? "\n": ";\n");
|
||||
}
|
||||
|
||||
_if_pgmout(strcmp, "\"%s\"", usbdev);
|
||||
_if_pgmout(strcmp, "\"%s\"", usbsn);
|
||||
_if_pgmout(strcmp, "\"%s\"", usbvendor);
|
||||
_if_pgmout(strcmp, "\"%s\"", usbproduct);
|
||||
_if_pgmout_str(strcmp, cfg_escape(pgm->usbdev), usbdev);
|
||||
_if_pgmout_str(strcmp, cfg_escape(pgm->usbsn), usbsn);
|
||||
_if_pgmout_str(strcmp, cfg_escape(pgm->usbvendor), usbvendor);
|
||||
_if_pgmout_str(strcmp, cfg_escape(pgm->usbproduct), usbproduct);
|
||||
|
||||
for(int i=0; i<N_PINS; 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)); \
|
||||
} while(0)
|
||||
|
||||
// Result must be a malloc()ed string
|
||||
#define _if_pgmout_str(cmp, result, component) do { \
|
||||
if(!base || cmp(base->component, pgm->component)) \
|
||||
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)); \
|
||||
} while(0)
|
||||
|
||||
// Result must be a malloc()ed string
|
||||
#define _partout_str(result, component) \
|
||||
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 { \
|
||||
if(!base || cmp(base->component, p->component)) \
|
||||
dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, result); \
|
||||
} while(0)
|
||||
|
||||
// Result must be a malloc()ed string
|
||||
#define _if_n_partout_str(cmp, n, result, component) do { \
|
||||
if(!base || cmp(base->component, p->component, n)) \
|
||||
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)); \
|
||||
} while(0)
|
||||
|
||||
// Result must be a malloc()ed string
|
||||
#define _memout_str(result, component) \
|
||||
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 { \
|
||||
if(!bm || cmp(bm->component, m->component, n)) \
|
||||
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, result); \
|
||||
} while(0)
|
||||
|
||||
#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 { \
|
||||
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)
|
||||
|
||||
#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 { \
|
||||
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)
|
||||
|
||||
// Result must be a malloc()ed string
|
||||
#define _cmderr(result, component) \
|
||||
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]
|
||||
SIGN [+-]
|
||||
|
||||
%x strng
|
||||
%x incl
|
||||
%x comment
|
||||
%option nounput
|
||||
|
@ -61,12 +60,19 @@ SIGN [+-]
|
|||
{SIGN}?{DIGIT}+"."{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; }
|
||||
|
||||
|
||||
|
||||
# { /* The following captures all '#' style comments to end of line */
|
||||
BEGIN(comment); }
|
||||
<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; }
|
||||
allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; }
|
||||
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 ""
|
||||
*
|
||||
* @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);
|
||||
|
||||
|
@ -1006,6 +1006,10 @@ extern double default_bitclock;
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *cfg_malloc(const char *funcname, size_t n);
|
||||
|
||||
char *cfg_strdup(const char *funcname, const char *s);
|
||||
|
||||
int init_config(void);
|
||||
|
||||
void cleanup_config(void);
|
||||
|
@ -1014,6 +1018,12 @@ int read_config(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
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -922,10 +922,7 @@ int main(int argc, char * argv [])
|
|||
progname,
|
||||
(upd->op == DEVICE_READ)? 'r': (upd->op == DEVICE_WRITE)? 'w': 'v',
|
||||
upd->filename, mtype);
|
||||
if ((upd->memtype = strdup(mtype)) == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
upd->memtype = cfg_strdup("main()", mtype);
|
||||
}
|
||||
|
||||
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;
|
||||
const char *nulp = cache_string("");
|
||||
|
||||
pgm = (PROGRAMMER *)malloc(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 = (PROGRAMMER *) cfg_malloc("pgm_new()", sizeof(*pgm));
|
||||
|
||||
pgm->id = lcreat(NULL, 0);
|
||||
pgm->usbpid = lcreat(NULL, 0);
|
||||
|
@ -162,24 +155,13 @@ PROGRAMMER * pgm_dup(const PROGRAMMER * const src)
|
|||
PROGRAMMER * pgm;
|
||||
LNODEID ln;
|
||||
|
||||
pgm = (PROGRAMMER *)malloc(sizeof(*pgm));
|
||||
if (pgm == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: out of memory allocating programmer structure\n",
|
||||
progname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pgm = (PROGRAMMER *) cfg_malloc("pgm_dup()", sizeof(*pgm));
|
||||
memcpy(pgm, src, sizeof(*pgm));
|
||||
|
||||
pgm->id = lcreat(NULL, 0);
|
||||
pgm->usbpid = lcreat(NULL, 0);
|
||||
for (ln = lfirst(src->usbpid); ln; ln = lnext(ln)) {
|
||||
int *ip = malloc(sizeof(int));
|
||||
if (ip == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: out of memory allocating programmer structure\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
int *ip = cfg_malloc("pgm_dup()", sizeof(int));
|
||||
*ip = *(int *) ldata(ln);
|
||||
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 ""
|
||||
*
|
||||
* @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 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 <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdio.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) {
|
||||
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
|
||||
strncpy(s, argi+1, arglen-2);
|
||||
unescape((unsigned char *) s, (unsigned char *) s);
|
||||
cfg_unescape(s, s);
|
||||
if (*argi == '\'') { // Single C-style character
|
||||
if(*s && s[1])
|
||||
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;
|
||||
size_t fnlen;
|
||||
|
||||
upd = (UPDATE *)malloc(sizeof(UPDATE));
|
||||
if (upd == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
upd = (UPDATE *) cfg_malloc("parse_op()", sizeof(UPDATE));
|
||||
|
||||
i = 0;
|
||||
p = s;
|
||||
|
@ -52,22 +48,12 @@ UPDATE * parse_op(char * s)
|
|||
if (*p != ':') {
|
||||
upd->memtype = NULL; /* default memtype, "flash", or "application" */
|
||||
upd->op = DEVICE_WRITE;
|
||||
upd->filename = (char *)malloc(strlen(buf) + 1);
|
||||
if (upd->filename == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
strcpy(upd->filename, buf);
|
||||
upd->filename = cfg_strdup("parse_op()", buf);
|
||||
upd->format = FMT_AUTO;
|
||||
return upd;
|
||||
}
|
||||
|
||||
upd->memtype = (char *)malloc(strlen(buf)+1);
|
||||
if (upd->memtype == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
strcpy(upd->memtype, buf);
|
||||
upd->memtype = cfg_strdup("parse_op()", buf);
|
||||
|
||||
p++;
|
||||
if (*p == 'r') {
|
||||
|
@ -118,10 +104,10 @@ UPDATE * parse_op(char * s)
|
|||
// and to binary for read operations:
|
||||
upd->format = upd->op == DEVICE_READ? FMT_RBIN: FMT_AUTO;
|
||||
fnlen = strlen(cp);
|
||||
upd->filename = (char *)malloc(fnlen + 1);
|
||||
upd->filename = (char *) cfg_malloc("parse_op()", fnlen + 1);
|
||||
} else {
|
||||
fnlen = p - cp;
|
||||
upd->filename = (char *)malloc(fnlen +1);
|
||||
upd->filename = (char *) cfg_malloc("parse_op()", fnlen +1);
|
||||
c = *++p;
|
||||
if (c && p[1])
|
||||
/* 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);
|
||||
upd->filename[fnlen] = 0;
|
||||
|
||||
|
@ -163,19 +143,15 @@ UPDATE * dup_update(UPDATE * upd)
|
|||
{
|
||||
UPDATE * u;
|
||||
|
||||
u = (UPDATE *)malloc(sizeof(UPDATE));
|
||||
if (u == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
u = (UPDATE *) cfg_malloc("dup_update()", sizeof(UPDATE));
|
||||
|
||||
memcpy(u, upd, sizeof(UPDATE));
|
||||
|
||||
if (upd->memtype != NULL)
|
||||
u->memtype = strdup(upd->memtype);
|
||||
u->memtype = cfg_strdup("dup_update()", upd->memtype);
|
||||
else
|
||||
u->memtype = NULL;
|
||||
u->filename = strdup(upd->filename);
|
||||
u->filename = cfg_strdup("dup_update()", upd->filename);
|
||||
|
||||
return u;
|
||||
}
|
||||
|
@ -184,14 +160,10 @@ UPDATE * new_update(int op, char * memtype, int filefmt, char * filename)
|
|||
{
|
||||
UPDATE * u;
|
||||
|
||||
u = (UPDATE *)malloc(sizeof(UPDATE));
|
||||
if (u == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
u = (UPDATE *) cfg_malloc("new_update()", sizeof(UPDATE));
|
||||
|
||||
u->memtype = strdup(memtype);
|
||||
u->filename = strdup(filename);
|
||||
u->memtype = cfg_strdup("new_update()", memtype);
|
||||
u->filename = cfg_strdup("new_update()", filename);
|
||||
u->op = op;
|
||||
u->format = filefmt;
|
||||
|
||||
|
|
Loading…
Reference in New Issue