Cache config_file components in AVRPART and PROGRAMMER structures

Some 90% of the space of AVRPART and some 50% of PROGRAMMER is occupied by a
4 kB array config_file[] that contains the configuration file name. In
preparation of developer options that output a raw dump of the part
descriptions, this commit changes the config_file components from a large
array, which is duplicated in each part and programmer description, to a
cached string for each config file allowing for smaller raw dumps.

This commit also changes the config file name to its realpath(), eg, shortens
unwarranted `/bin/../etc/` file name components. It also changes the global
variable names `infile` and `fileno` to cfg_infile and cfg_fileno for an ever
so slight improvement of code clarity.
This commit is contained in:
Stefan Rueger 2022-07-18 18:10:09 +01:00
parent 87401d341e
commit f95a1d3448
7 changed files with 80 additions and 35 deletions

View File

@ -568,7 +568,7 @@ AVRPART * avr_new_part(void)
p->reset_disposition = RESET_DEDICATED;
p->retry_pulse = PIN_AVR_SCK;
p->flags = AVRPART_SERIALOK | AVRPART_PARALLELOK | AVRPART_ENABLEPAGEPROGRAMMING;
p->config_file[0] = 0;
p->config_file = NULL;
p->lineno = 0;
memset(p->signature, 0xFF, 3);
p->ctl_stack_type = CTL_STACK_NONE;

View File

@ -50,8 +50,8 @@ LISTID part_list;
LISTID programmers;
bool is_alias;
int lineno;
const char * infile;
int cfg_lineno;
char * cfg_infile;
extern char * yytext;
@ -76,8 +76,8 @@ int init_config(void)
programmers = lcreat(NULL, 0);
is_alias = false;
lineno = 1;
infile = NULL;
cfg_lineno = 1;
cfg_infile = NULL;
return 0;
}
@ -99,7 +99,7 @@ int yyerror(char * errmsg, ...)
va_start(args, errmsg);
vsnprintf(message, sizeof(message), errmsg, args);
avrdude_message(MSG_INFO, "%s: error at %s:%d: %s\n", progname, infile, lineno, message);
avrdude_message(MSG_INFO, "%s: error at %s:%d: %s\n", progname, cfg_infile, cfg_lineno, message);
va_end(args);
@ -116,7 +116,7 @@ int yywarning(char * errmsg, ...)
va_start(args, errmsg);
vsnprintf(message, sizeof(message), errmsg, args);
avrdude_message(MSG_INFO, "%s: warning at %s:%d: %s\n", progname, infile, lineno, message);
avrdude_message(MSG_INFO, "%s: warning at %s:%d: %s\n", progname, cfg_infile, cfg_lineno, message);
va_end(args);
@ -329,15 +329,22 @@ int read_config(const char * file)
FILE * f;
int r;
f = fopen(file, "r");
if (f == NULL) {
avrdude_message(MSG_INFO, "%s: can't open config file \"%s\": %s\n",
if(!(cfg_infile = realpath(file, NULL))) {
avrdude_message(MSG_INFO, "%s: can't determine realpath() of config file \"%s\": %s\n",
progname, file, strerror(errno));
return -1;
}
lineno = 1;
infile = file;
f = fopen(cfg_infile, "r");
if (f == NULL) {
avrdude_message(MSG_INFO, "%s: can't open config file \"%s\": %s\n",
progname, cfg_infile, strerror(errno));
free(cfg_infile);
cfg_infile = NULL;
return -1;
}
cfg_lineno = 1;
yyin = f;
r = yyparse();
@ -349,5 +356,41 @@ int read_config(const char * file)
fclose(f);
if(cfg_infile) {
free(cfg_infile);
cfg_infile = NULL;
}
return r;
}
// Linear-search cache for a few often-referenced strings
char *cache_string(const char *file) {
static char **fnames;
static int n=0;
if(!file)
return NULL;
// Exists in cache?
for(int i=0; i<n; i++)
if(strcmp(fnames[i], file) == 0)
return fnames[i];
// Expand cache?
if(n%128 == 0) {
if(!(fnames = realloc(fnames, (n+128)*sizeof*fnames))) {
yyerror("cache_string(): out of memory");
return NULL;
}
}
fnames[n] = strdup(file);
if(!fnames[n]) {
yyerror("cache_string(): out of memory");
return NULL;
}
return fnames[n++];
}

View File

@ -50,8 +50,8 @@ extern FILE * yyin;
extern PROGRAMMER * current_prog;
extern AVRPART * current_part;
extern AVRMEM * current_mem;
extern int lineno;
extern const char * infile;
extern int cfg_lineno;
extern char * cfg_infile;
extern LISTID string_list;
extern LISTID number_list;
extern bool is_alias; // current entry is alias
@ -97,6 +97,8 @@ void pyytext(void);
char * dup_string(const char * str);
char * cache_string(const char * file);
#ifdef __cplusplus
}
#endif

View File

@ -288,10 +288,10 @@ prog_def :
existing_prog = locate_programmer(programmers, id);
if (existing_prog) {
{ /* temporarily set lineno to lineno of programmer start */
int temp = lineno; lineno = current_prog->lineno;
int temp = cfg_lineno; cfg_lineno = current_prog->lineno;
yywarning("programmer %s overwrites previous definition %s:%d.",
id, existing_prog->config_file, existing_prog->lineno);
lineno = temp;
cfg_lineno = temp;
}
lrmv_d(programmers, existing_prog);
pgm_free(existing_prog);
@ -311,8 +311,8 @@ prog_decl :
yyerror("could not create pgm instance");
YYABORT;
}
strcpy(current_prog->config_file, infile);
current_prog->lineno = lineno;
current_prog->config_file = cache_string(cfg_infile);
current_prog->lineno = cfg_lineno;
}
|
K_PROGRAMMER K_PARENT TKN_STRING
@ -329,8 +329,8 @@ prog_decl :
free_token($3);
YYABORT;
}
strcpy(current_prog->config_file, infile);
current_prog->lineno = lineno;
current_prog->config_file = cache_string(cfg_infile);
current_prog->lineno = cfg_lineno;
free_token($3);
}
;
@ -380,11 +380,11 @@ part_def :
existing_part = locate_part(part_list, current_part->id);
if (existing_part) {
{ /* temporarily set lineno to lineno of part start */
int temp = lineno; lineno = current_part->lineno;
int temp = cfg_lineno; cfg_lineno = current_part->lineno;
yywarning("part %s overwrites previous definition %s:%d.",
current_part->id,
existing_part->config_file, existing_part->lineno);
lineno = temp;
cfg_lineno = temp;
}
lrmv_d(part_list, existing_part);
avr_free_part(existing_part);
@ -402,8 +402,8 @@ part_decl :
yyerror("could not create part instance");
YYABORT;
}
strcpy(current_part->config_file, infile);
current_part->lineno = lineno;
current_part->config_file = cache_string(cfg_infile);
current_part->lineno = cfg_lineno;
} |
K_PART K_PARENT TKN_STRING
{
@ -420,8 +420,8 @@ part_decl :
free_token($3);
YYABORT;
}
strcpy(current_part->config_file, infile);
current_part->lineno = lineno;
current_part->config_file = cache_string(cfg_infile);
current_part->lineno = cfg_lineno;
free_token($3);
}
@ -1362,7 +1362,7 @@ mem_spec :
if (ps <= 0)
avrdude_message(MSG_INFO,
"%s, line %d: invalid page size %d, ignored\n",
infile, lineno, ps);
cfg_infile, cfg_lineno, ps);
else
current_mem->page_size = ps;
free_token($3);

View File

@ -73,19 +73,19 @@ SIGN [+-]
# { /* The following eats '#' style comments to end of line */
BEGIN(comment); }
<comment>[^\n] { /* eat comments */ }
<comment>\n { lineno++; BEGIN(INITIAL); }
<comment>\n { cfg_lineno++; BEGIN(INITIAL); }
"/*" { /* The following eats multiline C style comments */
int c;
int comment_start;
comment_start = lineno;
comment_start = cfg_lineno;
while (1) {
while (((c = input()) != '*') && (c != EOF)) {
/* eat up text of comment, but keep counting lines */
if (c == '\n')
lineno++;
cfg_lineno++;
}
if (c == '*') {
@ -256,7 +256,7 @@ yes { yylval=new_token(K_YES); return K_YES; }
"(" { yylval = NULL; pyytext(); return TKN_LEFT_PAREN; }
")" { yylval = NULL; pyytext(); return TKN_RIGHT_PAREN; }
"\n" { lineno++; }
"\n" { cfg_lineno++; }
[ \r\t]+ { /* ignore whitespace */ }
c: { yyerror("possible old-style config file entry\n"

View File

@ -277,8 +277,8 @@ typedef struct avrpart {
LISTID mem; /* avr memory definitions */
LISTID mem_alias; /* memory alias definitions */
char config_file[PATH_MAX]; /* config file where defined */
int lineno; /* config file line number */
char *config_file; /* config file where defined */
int lineno; /* config file line number */
} AVRPART;
#define AVR_MEMDESCLEN 64
@ -726,7 +726,7 @@ typedef struct programmer_t {
int (*parseextparams) (struct programmer_t * pgm, LISTID xparams);
void (*setup) (struct programmer_t * pgm);
void (*teardown) (struct programmer_t * pgm);
char config_file[PATH_MAX]; /* config file where defined */
char *config_file; /* config file where defined */
int lineno; /* config file line number */
void *cookie; /* for private use by the programmer */
char flag; /* for private use of the programmer */

View File

@ -79,7 +79,7 @@ PROGRAMMER * pgm_new(void)
pgm->usbpid = lcreat(NULL, 0);
pgm->desc[0] = 0;
pgm->type[0] = 0;
pgm->config_file[0] = 0;
pgm->config_file = NULL;
pgm->lineno = 0;
pgm->baudrate = 0;
pgm->initpgm = NULL;