From 81136688f677473a27ca8aeae875e4282de907e2 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sun, 7 Aug 2022 08:53:24 +0100 Subject: [PATCH 01/19] Establish a third option to print out part definitions Introduced -p /A, which prints what -p /S used to print, ie, all components of the part structures including the default ones. Now -p /S prints the expanded part structure without use of parent and without printing default values. This functionality is new and predominantly needed for checking specific avrdude.conf entries, eg, avrdude -p*/St | grep pollindex The option -p /s continues to print a short entry of `avrdude.conf` using its parent if so defined: $ avrdude -p m328p/s part parent "m328" desc = "ATmega328P"; id = "m328p"; signature = 0x1e 0x95 0x0f; ; --- src/developer_opts.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/developer_opts.c b/src/developer_opts.c index b82c1805..f80f5537 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -601,7 +601,7 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) { // -p */[cdosw*] void dev_output_part_defs(char *partdesc) { - bool cmdok, waits, opspi, descs, strct, cmpst, raw, all, tsv; + bool cmdok, waits, opspi, descs, astrc, strct, cmpst, raw, all, tsv; char *flags; int nprinted; AVRPART *nullpart = avr_new_part(); @@ -612,7 +612,7 @@ void dev_output_part_defs(char *partdesc) { if(!flags && !strcmp(partdesc, "*")) // treat -p * as if it was -p */* flags = "*"; - if(!*flags || !strchr("cdosSrw*t", *flags)) { + if(!*flags || !strchr("cdoASsrw*t", *flags)) { dev_info("%s: flags for developer option -p / not recognised\n", progname); dev_info( "Wildcard examples (these need protecting in the shell through quoting):\n" @@ -621,14 +621,15 @@ void dev_output_part_defs(char *partdesc) { " *32[0-9] matches ATmega329, ATmega325 and ATmega328\n" " *32? matches ATmega329, ATmega32A, ATmega325 and ATmega328\n" "Flags (one or more of the characters below):\n" - " c check and report errors in address bits of SPI commands\n" " d description of core part features\n" - " o opcodes for SPI programming parts and memories\n" - " S show entries of avrdude.conf parts with all values\n" - " s show entries of avrdude.conf parts with necessary values\n" + " A show entries of avrdude.conf parts with all values\n" + " S show entries of avrdude.conf parts with necessary values\n" + " s show short entries of avrdude.conf parts using parent\n" " r show entries of avrdude.conf parts as raw dump\n" + " c check and report errors in address bits of SPI commands\n" + " o opcodes for SPI programming parts and memories\n" " w wd_... constants for ISP parts\n" - " * all of the above except s\n" + " * all of the above except s and S\n" " t use tab separated values as much as possible\n" "Examples:\n" " $ avrdude -p ATmega328P/s\n" @@ -638,7 +639,7 @@ void dev_output_part_defs(char *partdesc) { " -p * is the same as -p */*\n" " This help message is printed using any unrecognised flag, eg, -p/h\n" " Leaving no space after -p can be an OK substitute for quoting in shells\n" - " /s and /S outputs are designed to be used as input in avrdude.conf\n" + " /s, /S and /A outputs are designed to be used as input in avrdude.conf\n" " Sorted /r output should stay invariant when rearranging avrdude.conf\n" " The /c, /o and /w flags are less generic and may be removed sometime\n" " These options are just to help development, so not further documented\n" @@ -654,8 +655,9 @@ void dev_output_part_defs(char *partdesc) { descs = all || !!strchr(flags, 'd'); opspi = all || !!strchr(flags, 'o'); waits = all || !!strchr(flags, 'w'); - strct = all || !!strchr(flags, 'S'); + astrc = all || !!strchr(flags, 'A'); raw = all || !!strchr(flags, 'r'); + strct = !!strchr(flags, 'S'); cmpst = !!strchr(flags, 's'); tsv = !!strchr(flags, 't'); @@ -687,8 +689,11 @@ void dev_output_part_defs(char *partdesc) { if(!part_match(partdesc, p->desc) && !part_match(partdesc, p->id)) continue; - if(strct || cmpst) - dev_part_strct(p, tsv, !cmpst? NULL: p->parent_id? locate_part(part_list, p->parent_id): nullpart); + if(astrc || strct || cmpst) + dev_part_strct(p, tsv, + astrc? NULL: + strct? nullpart: + p->parent_id? locate_part(part_list, p->parent_id): nullpart); if(raw) dev_part_raw(p); From 08049a40ea661494f8d5465055b216522d5e3d22 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sun, 7 Aug 2022 14:05:54 +0100 Subject: [PATCH 02/19] Implement dev option -c */[ASsrt] skeleton Also changed usbdev, usbsn, usbvendor and usbproduct components from PROGRAMMER structure to be cached string pointers rather than fixed-size arrays. These will be initialised by pgm_new() with a pointer to nul; --- src/avrftdi.c | 2 +- src/avrpart.c | 5 +- src/config.h | 2 - src/config_gram.y | 12 ++--- src/developer_opts.c | 124 +++++++++++++++++++++++++++++++++++++++++-- src/developer_opts.h | 1 + src/ft245r.c | 4 +- src/libavrdude.h | 14 ++--- src/main.c | 8 ++- src/pgm.c | 12 +++-- src/ser_avrdoper.c | 4 +- src/usbasp.c | 8 +-- 12 files changed, 159 insertions(+), 37 deletions(-) diff --git a/src/avrftdi.c b/src/avrftdi.c index f0c07a6a..315f23e8 100644 --- a/src/avrftdi.c +++ b/src/avrftdi.c @@ -651,7 +651,7 @@ static int avrftdi_pin_setup(PROGRAMMER * pgm) static int avrftdi_open(PROGRAMMER * pgm, char *port) { int vid, pid, interface, index, err; - char * serial, *desc; + const char *serial, *desc; avrftdi_t* pdata = to_pdata(pgm); diff --git a/src/avrpart.c b/src/avrpart.c index 4fc6304f..970dfde8 100644 --- a/src/avrpart.c +++ b/src/avrpart.c @@ -672,6 +672,7 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p, AVRPART * avr_new_part(void) { AVRPART * p; + char *nulp = cache_string(""); p = (AVRPART *)malloc(sizeof(AVRPART)); if (p == NULL) { @@ -686,8 +687,8 @@ 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->parent_id = NULL; - p->config_file = NULL; + p->parent_id = nulp; + p->config_file = nulp; p->lineno = 0; memset(p->signature, 0xFF, 3); p->ctl_stack_type = CTL_STACK_NONE; diff --git a/src/config.h b/src/config.h index a20af733..a7d2563d 100644 --- a/src/config.h +++ b/src/config.h @@ -101,8 +101,6 @@ void pyytext(void); char * dup_string(const char * str); -char * cache_string(const char * file); - #ifdef __cplusplus } #endif diff --git a/src/config_gram.y b/src/config_gram.y index ce11b924..552832ec 100644 --- a/src/config_gram.y +++ b/src/config_gram.y @@ -532,8 +532,7 @@ prog_parm_conntype_id: prog_parm_usb: K_USBDEV TKN_EQUAL TKN_STRING { { - strncpy(current_prog->usbdev, $3->value.string, PGM_USBSTRINGLEN); - current_prog->usbdev[PGM_USBSTRINGLEN-1] = 0; + current_prog->usbdev = cache_string($3->value.string); free_token($3); } } | @@ -546,22 +545,19 @@ prog_parm_usb: K_USBPID TKN_EQUAL usb_pid_list | K_USBSN TKN_EQUAL TKN_STRING { { - strncpy(current_prog->usbsn, $3->value.string, PGM_USBSTRINGLEN); - current_prog->usbsn[PGM_USBSTRINGLEN-1] = 0; + current_prog->usbsn = cache_string($3->value.string); free_token($3); } } | K_USBVENDOR TKN_EQUAL TKN_STRING { { - strncpy(current_prog->usbvendor, $3->value.string, PGM_USBSTRINGLEN); - current_prog->usbvendor[PGM_USBSTRINGLEN-1] = 0; + current_prog->usbvendor = cache_string($3->value.string); free_token($3); } } | K_USBPRODUCT TKN_EQUAL TKN_STRING { { - strncpy(current_prog->usbproduct, $3->value.string, PGM_USBSTRINGLEN); - current_prog->usbproduct[PGM_USBSTRINGLEN-1] = 0; + current_prog->usbproduct = cache_string($3->value.string); free_token($3); } } diff --git a/src/developer_opts.c b/src/developer_opts.c index f80f5537..8aea0bb2 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -436,7 +436,7 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) { dev_info("#------------------------------------------------------------\n"); dev_info("# %s\n", p->desc); dev_info("#------------------------------------------------------------\n"); - if(p->parent_id) + if(p->parent_id && *p->parent_id) dev_info("\npart parent \"%s\"\n", p->parent_id); else dev_info("\npart\n"); @@ -597,9 +597,7 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) { } - - -// -p */[cdosw*] +// -p */[dASsrcow*t] void dev_output_part_defs(char *partdesc) { bool cmdok, waits, opspi, descs, astrc, strct, cmpst, raw, all, tsv; char *flags; @@ -693,7 +691,7 @@ void dev_output_part_defs(char *partdesc) { dev_part_strct(p, tsv, astrc? NULL: strct? nullpart: - p->parent_id? locate_part(part_list, p->parent_id): nullpart); + p->parent_id && *p->parent_id? locate_part(part_list, p->parent_id): nullpart); if(raw) dev_part_raw(p); @@ -891,3 +889,119 @@ void dev_output_part_defs(char *partdesc) { } } } + + +static void dev_pgm_raw(PROGRAMMER *pgm) { + PROGRAMMER dp; + + memcpy(&dp, pgm, sizeof dp); + dev_raw_dump((unsigned char *) &dp, sizeof dp, pgm->desc, "pgm", 0); +} + + +static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) { + if(!tsv) { + int firstid = 1; + + dev_info("#------------------------------------------------------------\n"); + dev_info("# "); + for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) { + if(!firstid) + dev_info("/"); + firstid = 0; + dev_info("%s", ldata(ln)); + } + dev_info("\n"); + dev_info("#------------------------------------------------------------\n"); + if(pgm->parent_id && *pgm->parent_id) + dev_info("\nprogrammer parent \"%s\"\n", pgm->parent_id); + else + dev_info("\nprogrammer\n"); + } + + if(!tsv) + dev_info(";\n"); +} + + +// -c */[ASsrt] +void dev_output_pgm_defs(char *pgmid) { + bool astrc, strct, cmpst, raw, tsv; + char *flags; + int nprinted; + PROGRAMMER *nullpgm = pgm_new(); + + if((flags = strchr(pgmid, '/'))) + *flags++ = 0; + + if(!flags && !strcmp(pgmid, "*")) // treat -c * as if it was -c */A + flags = "A"; + + if(!*flags || !strchr("ASsrt", *flags)) { + dev_info("%s: flags for developer option -c / not recognised\n", progname); + dev_info( + "Wildcard examples (these need protecting in the shell through quoting):\n" + " * all known programmers\n" + " avrftdi just this programmer\n" + " jtag*pdi matches jtag2pdi, jtag3pdi, jtag3updi and jtag2updi\n" + " jtag?pdi matches jtag2pdi and jtag3pdi\n" + "Flags (one or more of the characters below):\n" + " A show entries of avrdude.conf programmers with all values\n" + " S show entries of avrdude.conf programmers with necessary values\n" + " s show short entries of avrdude.conf programmers using parent\n" + " r show entries of avrdude.conf programmers as raw dump\n" + " t use tab separated values as much as possible\n" + "Examples:\n" + " $ avrdude -c usbasp/s\n" + " $ avrdude -c */st | grep baudrate\n" + " $ avrdude -c */r | sort\n" + "Notes:\n" + " -c * is the same as -c */A\n" + " This help message is printed using any unrecognised flag, eg, -c/h\n" + " Leaving no space after -c can be an OK substitute for quoting in shells\n" + " /s, /S and /A outputs are designed to be used as input in avrdude.conf\n" + " Sorted /r output should stay invariant when rearranging avrdude.conf\n" + " These options are just to help development, so not further documented\n" + ); + return; + } + + // redirect stderr to stdout + fflush(stderr); fflush(stdout); dup2(1, 2); + + astrc = !!strchr(flags, 'A'); + strct = !!strchr(flags, 'S'); + cmpst = !!strchr(flags, 's'); + raw = !!strchr(flags, 'r'); + tsv = !!strchr(flags, 't'); + + nprinted = dev_nprinted; + + LNODEID ln1, ln2; + for(ln1=lfirst(programmers); ln1; ln1=lnext(ln1)) { + PROGRAMMER *pgm = ldata(ln1); + int matched = 0; + for(ln2=lfirst(pgm->id); ln2; ln2=lnext(ln2)) { + if(part_match(pgmid, ldata(ln2))) { + matched = 1; + break; + } + } + if(!matched) + continue; + + if(dev_nprinted > nprinted) { + dev_info("\n"); + nprinted = dev_nprinted; + } + + if(astrc || strct || cmpst) + dev_pgm_strct(pgm, tsv, + astrc? NULL: + strct? nullpgm: + pgm->parent_id && *pgm->parent_id? locate_programmer(programmers, pgm->parent_id): nullpgm); + + if(raw) + dev_pgm_raw(pgm); + } +} diff --git a/src/developer_opts.h b/src/developer_opts.h index 6c4b3b71..2079c109 100644 --- a/src/developer_opts.h +++ b/src/developer_opts.h @@ -20,5 +20,6 @@ #define developer_opts_h void dev_output_part_defs(char *partdesc); +void dev_output_pgm_defs(char *programmer); #endif diff --git a/src/ft245r.c b/src/ft245r.c index 874167ac..04790143 100644 --- a/src/ft245r.c +++ b/src/ft245r.c @@ -851,7 +851,7 @@ static int ft245r_open(PROGRAMMER * pgm, char * port) { avrdude_message(MSG_NOTICE, "%s: ft245r_open(): no device identifier in portname, using default\n", progname); - pgm->usbsn[0] = 0; + pgm->usbsn = cache_string(""); devnum = 0; } else { if (strlen(device) == 8 ){ // serial number @@ -863,7 +863,7 @@ static int ft245r_open(PROGRAMMER * pgm, char * port) { device); } // copy serial number to pgm struct - strcpy(pgm->usbsn, device); + pgm->usbsn = cache_string(device); // and use first device with matching serial (should be unique) devnum = 0; } diff --git a/src/libavrdude.h b/src/libavrdude.h index 23905953..7dcab3c2 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -217,7 +217,7 @@ typedef struct opcode { typedef struct avrpart { char desc[AVR_DESCLEN]; /* long part name */ char id[AVR_IDLEN]; /* short part name */ - char * parent_id; /* parent id if set, for -p.../s */ + const char * parent_id; /* parent id if set, for -p.../s */ char family_id[AVR_FAMILYIDLEN+1]; /* family id in the SIB (avr8x) */ int hvupdi_variant; /* HV pulse on UPDI pin, no pin or RESET pin */ int stk500_devcode; /* stk500 device code */ @@ -280,7 +280,7 @@ typedef struct avrpart { LISTID mem; /* avr memory definitions */ LISTID mem_alias; /* memory alias definitions */ - char *config_file; /* config file where defined */ + const char * config_file; /* config file where defined */ int lineno; /* config file line number */ } AVRPART; @@ -640,7 +640,6 @@ extern struct serial_device usbhid_serdev; #define PGM_DESCLEN 80 #define PGM_PORTLEN PATH_MAX #define PGM_TYPELEN 32 -#define PGM_USBSTRINGLEN 256 typedef enum { EXIT_VCC_UNSPEC, @@ -672,7 +671,7 @@ typedef struct programmer_t { char desc[PGM_DESCLEN]; char type[PGM_TYPELEN]; char port[PGM_PORTLEN]; - char *parent_id; + const char *parent_id; void (*initpgm)(struct programmer_t * pgm); unsigned int pinno[N_PINS]; struct pindef_t pin[N_PINS]; @@ -685,8 +684,7 @@ typedef struct programmer_t { int baudrate; int usbvid; LISTID usbpid; - char usbdev[PGM_USBSTRINGLEN], usbsn[PGM_USBSTRINGLEN]; - char usbvendor[PGM_USBSTRINGLEN], usbproduct[PGM_USBSTRINGLEN]; + const char *usbdev, *usbsn, *usbvendor, *usbproduct; double bitclock; /* JTAG ICE clock period in microseconds */ int ispdelay; /* ISP clock delay */ union filedescriptor fd; @@ -740,7 +738,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; /* config file where defined */ + const 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 */ @@ -989,6 +987,8 @@ void cleanup_config(void); int read_config(const char * file); +char *cache_string(const char *file); + #ifdef __cplusplus } #endif diff --git a/src/main.c b/src/main.c index 9f72847f..83bde3e9 100644 --- a/src/main.c +++ b/src/main.c @@ -754,7 +754,7 @@ int main(int argc, char * argv []) avrdude_message(MSG_NOTICE, "\n"); - // developer option -p /[*codws] prints various aspects of part descriptions and exits + // Developer option -p /[dASsrcow*t] prints part description(s) and exits if(partdesc && (strcmp(partdesc, "*") == 0 || strchr(partdesc, '/'))) { dev_output_part_defs(partdesc); exit(1); @@ -770,6 +770,12 @@ int main(int argc, char * argv []) } } + // Developer option -c /[ASsrt] prints programmer description(s) and exits + if(programmer && (strcmp(programmer, "*") == 0 || strchr(programmer, '/'))) { + dev_output_pgm_defs(programmer); + exit(1); + } + if (programmer) { if (strcmp(programmer, "?") == 0) { avrdude_message(MSG_INFO, "\n"); diff --git a/src/pgm.c b/src/pgm.c index dd38552f..a4e0ed54 100644 --- a/src/pgm.c +++ b/src/pgm.c @@ -65,6 +65,7 @@ PROGRAMMER * pgm_new(void) { int i; PROGRAMMER * pgm; + char *nulp = cache_string(""); pgm = (PROGRAMMER *)malloc(sizeof(*pgm)); if (pgm == NULL) { @@ -79,13 +80,18 @@ PROGRAMMER * pgm_new(void) pgm->usbpid = lcreat(NULL, 0); pgm->desc[0] = 0; pgm->type[0] = 0; - pgm->parent_id = NULL; - pgm->config_file = NULL; + pgm->parent_id = nulp; + pgm->config_file = nulp; pgm->lineno = 0; pgm->baudrate = 0; pgm->initpgm = NULL; pgm->hvupdi_support = lcreat(NULL, 0); + pgm->usbdev = nulp; + pgm->usbsn = nulp; + pgm->usbvendor = nulp; + pgm->usbproduct = nulp; + for (i=0; ipinno[i] = 0; pin_clear_all(&(pgm->pin[i])); @@ -146,7 +152,7 @@ void pgm_free(PROGRAMMER * const p) ldestroy_cb(p->usbpid, free); p->id = NULL; p->usbpid = NULL; - /* do not free p->parent_id nor p->config_file */ + /* do not free p->parent_id, p->config_file, p->usbdev, p->usbsn, p->usbvendor or p-> usbproduct */ /* p->cookie is freed by pgm_teardown */ free(p); } diff --git a/src/ser_avrdoper.c b/src/ser_avrdoper.c index a8414403..e459f921 100644 --- a/src/ser_avrdoper.c +++ b/src/ser_avrdoper.c @@ -65,8 +65,8 @@ static int avrdoperRxPosition = 0; /* amount of bytes already consu /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ -static int usbOpenDevice(union filedescriptor *fdp, int vendor, char *vendorName, - int product, char *productName, int doReportIDs) +static int usbOpenDevice(union filedescriptor *fdp, int vendor, const char *vendorName, + int product, const char *productName, int doReportIDs) { hid_device *dev; diff --git a/src/usbasp.c b/src/usbasp.c index 250c8a22..2b4c4831 100644 --- a/src/usbasp.c +++ b/src/usbasp.c @@ -160,9 +160,9 @@ static int usbasp_transmit(PROGRAMMER * pgm, unsigned char receive, unsigned char functionid, const unsigned char *send, unsigned char *buffer, int buffersize); #ifdef USE_LIBUSB_1_0 -static int usbOpenDevice(libusb_device_handle **device, int vendor, char *vendorName, int product, char *productName); +static int usbOpenDevice(libusb_device_handle **device, int vendor, const char *vendorName, int product, const char *productName); #else -static int usbOpenDevice(usb_dev_handle **device, int vendor, char *vendorName, int product, char *productName); +static int usbOpenDevice(usb_dev_handle **device, int vendor, const char *vendorName, int product, const char *productName); #endif // interface - prog. static int usbasp_open(PROGRAMMER * pgm, char * port); @@ -337,7 +337,7 @@ static int usbasp_transmit(PROGRAMMER * pgm, */ #ifdef USE_LIBUSB_1_0 static int usbOpenDevice(libusb_device_handle **device, int vendor, - char *vendorName, int product, char *productName) + const char *vendorName, int product, const char *productName) { libusb_device_handle *handle = NULL; int errorCode = USB_ERROR_NOTFOUND; @@ -412,7 +412,7 @@ static int usbOpenDevice(libusb_device_handle **device, int vendor, } #else static int usbOpenDevice(usb_dev_handle **device, int vendor, - char *vendorName, int product, char *productName) + const char *vendorName, int product, const char *productName) { struct usb_bus *bus; struct usb_device *dev; From 075dee1dd33da28be5472fad6d478421e970d1ca Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sun, 7 Aug 2022 17:52:17 +0100 Subject: [PATCH 03/19] Implement -c */r (raw dump of programmer structure) --- src/developer_opts.c | 134 ++++++++++++++++++++++++++++--------------- src/libavrdude.h | 22 ++++--- 2 files changed, 101 insertions(+), 55 deletions(-) diff --git a/src/developer_opts.c b/src/developer_opts.c index 8aea0bb2..8d8c183c 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -51,7 +52,7 @@ #include "developer_opts.h" #include "developer_opts_private.h" -// return 0 if op code would encode (essentially) the same SPI command +// Return 0 if op code would encode (essentially) the same SPI command static int opcodecmp(OPCODE *op1, OPCODE *op2, int opnum) { char *opstr1, *opstr2, *p; int cmp; @@ -68,7 +69,7 @@ static int opcodecmp(OPCODE *op1, OPCODE *op2, int opnum) { exit(1); } - // don't care x and 0 are functionally equivalent + // Don't care x and 0 are functionally equivalent for(p=opstr1; *p; p++) if(*p == 'x') *p = '0'; @@ -108,7 +109,7 @@ static void printallopcodes(AVRPART *p, const char *d, OPCODE **opa) { -// mnemonic characterisation of flags +// Mnemonic characterisation of flags static char *parttype(AVRPART *p) { static char type[1024]; @@ -144,7 +145,7 @@ static char *parttype(AVRPART *p) { } -// check whether address bits are where they should be in ISP commands +// Check whether address bits are where they should be in ISP commands static void checkaddr(int memsize, int pagesize, int opnum, OPCODE *op, AVRPART *p, AVRMEM *m) { int i, lo, hi; const char *opstr = opcodename(opnum); @@ -152,7 +153,7 @@ static void checkaddr(int memsize, int pagesize, int opnum, OPCODE *op, AVRPART lo = intlog2(pagesize); hi = intlog2(memsize-1); - // address bits should be between positions lo and hi (and fall in line), outside should be 0 or don't care + // Address bits should be between positions lo and hi (and fall in line), outside should be 0 or don't care for(i=0; i<16; i++) { // ISP programming only deals with 16-bit addresses (words for flash, bytes for eeprom) if(i < lo || i > hi) { if(op->bit[i+8].type != AVR_CMDBIT_IGNORE && !(op->bit[i+8].type == AVR_CMDBIT_VALUE && op->bit[i+8].value == 0)) { @@ -168,7 +169,7 @@ static void checkaddr(int memsize, int pagesize, int opnum, OPCODE *op, AVRPART dev_info(".cmderr\t%s\t%s-%s\tbit %d inconsistent: a%d specified as a%d\n", p->desc, m->desc, opstr, i+8, i, op->bit[i+8].bitno); } } - for(i=0; i<32; i++) // command bits 8..23 should not contain address bits + for(i=0; i<32; i++) // Command bits 8..23 should not contain address bits if((i<8 || i>23) && op->bit[i].type == AVR_CMDBIT_ADDRESS) dev_info(".cmderr\t%s\t%s-%s\tbit %d contains a%d which it shouldn't\n", p->desc, m->desc, opstr, i, op->bit[i].bitno); } @@ -180,7 +181,7 @@ static char *dev_sprintf(const char *fmt, ...) { char *p = NULL; va_list ap; - // compute size + // Compute size va_start(ap, fmt); size = vsnprintf(p, size, fmt, ap); va_end(ap); @@ -188,7 +189,7 @@ static char *dev_sprintf(const char *fmt, ...) { if(size < 0) return NULL; - size++; // for temrinating '\0' + size++; // For temrinating '\0' if(!(p = malloc(size))) return NULL; @@ -228,7 +229,7 @@ static int dev_part_strct_entry(bool tsv, char *col0, char *col1, char *col2, co const char *n = name? name: "name_error"; const char *c = cont? cont: "cont_error"; - if(tsv) { // tab separated values + if(tsv) { // Tab separated values if(col0) { dev_info("%s\t", col0); if(col1) { @@ -239,7 +240,7 @@ static int dev_part_strct_entry(bool tsv, char *col0, char *col1, char *col2, co } } dev_info("%s\t%s\n", n, c); - } else { // grammar conform + } else { // Grammar conform int indent = col2 && strcmp(col2, "part"); printf("%*s%-*s = %s;\n", indent? 8: 4, "", indent? 15: 19, n, c); @@ -285,7 +286,7 @@ static int intcmp(int a, int b) { } -// deep copies for comparison and raw output +// Deep copies for comparison and raw output typedef struct { AVRMEM base; @@ -297,19 +298,19 @@ static int avrmem_deep_copy(AVRMEMdeep *d, AVRMEM *m) { d->base = *m; - // zap all bytes beyond terminating nul of desc array + // Zap all bytes beyond terminating nul of desc array len = strlen(m->desc)+1; if(len < sizeof m->desc) memset(d->base.desc + len, 0, sizeof m->desc - len); - // zap address values + // Zap address values d->base.buf = NULL; d->base.tags = NULL; for(int i=0; ibase.op[i] = NULL; - // copy over the SPI operations themselves + // Copy over the SPI operations themselves memset(d->base.op, 0, sizeof d->base.op); memset(d->ops, 0, sizeof d->ops); for(size_t i=0; iops/sizeof *d->ops; i++) @@ -353,7 +354,7 @@ static int avrpart_deep_copy(AVRPARTdeep *d, AVRPART *p) { d->base.config_file = NULL; d->base.lineno = 0; - // zap all bytes beyond terminating nul of desc, id and family_id array + // Zap all bytes beyond terminating nul of desc, id and family_id array len = strlen(p->desc); if(len < sizeof p->desc) memset(d->base.desc + len, 0, sizeof p->desc - len); @@ -366,20 +367,20 @@ static int avrpart_deep_copy(AVRPARTdeep *d, AVRPART *p) { if(len < sizeof p->id) memset(d->base.id + len, 0, sizeof p->id - len); - // zap address values + // Zap address values d->base.mem = NULL; d->base.mem_alias = NULL; for(int i=0; ibase.op[i] = NULL; - // copy over the SPI operations + // Copy over the SPI operations memset(d->base.op, 0, sizeof d->base.op); memset(d->ops, 0, sizeof d->ops); for(int i=0; iop[i]) d->ops[i] = *p->op[i]; - // fill in all memories we got in defined order + // Fill in all memories we got in defined order di = 0; for(size_t mi=0; mi < sizeof avr_mem_order/sizeof *avr_mem_order && avr_mem_order[mi]; mi++) { m = p->mem? avr_locate_mem(p, avr_mem_order[mi]): NULL; @@ -396,23 +397,28 @@ static int avrpart_deep_copy(AVRPARTdeep *d, AVRPART *p) { return di; } + static char txtchar(unsigned char in) { in &= 0x7f; return in == ' '? '_': in > ' ' && in < 0x7f? in: '.'; } +static void dev_raw_dump(const char *p, int nbytes, const char *name, const char *sub, int idx) { + int n = (nbytes + 31)/32; -static void dev_raw_dump(unsigned char *p, int nbytes, const char *name, const char *sub, int idx) { - unsigned char *end = p+nbytes; - int n = ((end - p) + 15)/16; - - for(int i=0; idesc, "part", 0); - dev_raw_dump((unsigned char *) &dp.ops, sizeof dp.ops, part->desc, "ops", 1); + dev_raw_dump((char *) &dp.base, sizeof dp.base, part->desc, "part", 0); + dev_raw_dump((char *) &dp.ops, sizeof dp.ops, part->desc, "ops", 1); for(int i=0; idesc, dp.mems[i].base.desc, i+2); + dev_raw_dump((char *) (dp.mems+i), sizeof dp.mems[i], part->desc, dp.mems[i].base.desc, i+2); } @@ -527,7 +533,7 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) { _if_partout(intcmp, "0x%02x", idr); _if_partout(intcmp, "0x%02x", rampz); _if_partout(intcmp, "0x%02x", spmcr); - _if_partout(intcmp, "0x%02x", eecr); // why is eecr an unsigned short? + _if_partout(intcmp, "0x%02x", eecr); // Why is eecr an unsigned short? _if_partout(intcmp, "0x%04x", mcu_base); _if_partout(intcmp, "0x%04x", nvm_base); _if_partout(intcmp, "0x%04x", ocd_base); @@ -553,7 +559,7 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) { bm = avr_new_memtype(); if(!tsv) { - if(!memorycmp(bm, m)) // same memory bit for bit, no need to instantiate + if(!memorycmp(bm, m)) // Same memory bit for bit, no need to instantiate continue; dev_info("\n memory \"%s\"\n", m->desc); @@ -562,7 +568,7 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) { _if_memout_yn(paged); _if_memout(intcmp, m->size > 8192? "0x%x": "%d", size); _if_memout(intcmp, "%d", page_size); - _if_memout(intcmp, "%d", num_pages); // why can AVRDUDE not compute this? + _if_memout(intcmp, "%d", num_pages); _if_memout(intcmp, "0x%x", offset); _if_memout(intcmp, "%d", min_write_delay); _if_memout(intcmp, "%d", max_write_delay); @@ -607,7 +613,7 @@ void dev_output_part_defs(char *partdesc) { if((flags = strchr(partdesc, '/'))) *flags++ = 0; - if(!flags && !strcmp(partdesc, "*")) // treat -p * as if it was -p */* + if(!flags && !strcmp(partdesc, "*")) // Treat -p * as if it was -p */* flags = "*"; if(!*flags || !strchr("cdoASsrw*t", *flags)) { @@ -645,7 +651,7 @@ void dev_output_part_defs(char *partdesc) { return; } - // redirect stderr to stdout + // Redirect stderr to stdout fflush(stderr); fflush(stdout); dup2(1, 2); all = *flags == '*'; @@ -660,14 +666,14 @@ void dev_output_part_defs(char *partdesc) { tsv = !!strchr(flags, 't'); - // go through all memories and add them to the memory order list + // Go through all memories and add them to the memory order list for(LNODEID ln1 = lfirst(part_list); ln1; ln1 = lnext(ln1)) { AVRPART *p = ldata(ln1); if(p->mem) for(LNODEID lnm=lfirst(p->mem); lnm; lnm=lnext(lnm)) avr_add_mem_order(((AVRMEM *) ldata(lnm))->desc); - // same for aliased memories (though probably not needed) + // Same for aliased memories (though probably not needed) if(p->mem_alias) for(LNODEID lnm=lfirst(p->mem_alias); lnm; lnm=lnext(lnm)) avr_add_mem_order(((AVRMEM_ALIAS *) ldata(lnm))->desc); @@ -696,7 +702,7 @@ void dev_output_part_defs(char *partdesc) { if(raw) dev_part_raw(p); - // identify core flash and eeprom parameters + // Identify core flash and eeprom parameters flashsize = flashoffset = flashpagesize = eepromsize = eepromoffset = eeprompagesize = 0; if(p->mem) { @@ -715,7 +721,7 @@ void dev_output_part_defs(char *partdesc) { } } - // "real" entries don't seem to have a space in their desc (a bit hackey) + // "Real" entries don't seem to have a space in their desc (a bit hackey) if(flashsize && !strchr(p->desc, ' ')) { int ok, nfuses; AVRMEM *m; @@ -819,7 +825,7 @@ void dev_output_part_defs(char *partdesc) { } else ok &= ~DEV_SPI_CALIBRATION; - // actually, some AT90S... parts cannot read, only write lock bits :-0 + // Actually, some AT90S... parts cannot read, only write lock bits :-0 if( ! ((m = avr_locate_mem(p, "lock")) && m->op[AVR_OP_WRITE])) ok &= ~DEV_SPI_LOCK; @@ -866,14 +872,14 @@ void dev_output_part_defs(char *partdesc) { } } - // print wait delays for AVR family parts + // Print wait delays for AVR family parts if(waits) { if(!(p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_UPDI | AVRPART_HAS_TPI | AVRPART_AVR32))) dev_info(".wd_chip_erase %.3f ms %s\n", p->chip_erase_delay/1000.0, p->desc); if(p->mem) { for(LNODEID lnm=lfirst(p->mem); lnm; lnm=lnext(lnm)) { AVRMEM *m = ldata(lnm); - // write delays not needed for read-only calibration and signature memories + // Write delays not needed for read-only calibration and signature memories if(strcmp(m->desc, "calibration") && strcmp(m->desc, "signature")) { if(!(p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_UPDI | AVRPART_HAS_TPI | AVRPART_AVR32))) { if(m->min_write_delay == m->max_write_delay) @@ -893,9 +899,45 @@ void dev_output_part_defs(char *partdesc) { static void dev_pgm_raw(PROGRAMMER *pgm) { PROGRAMMER dp; + int len, idx; + char *id = ldata(lfirst(pgm->id)); + LNODEID ln; memcpy(&dp, pgm, sizeof dp); - dev_raw_dump((unsigned char *) &dp, sizeof dp, pgm->desc, "pgm", 0); + + // Dump id, usbpid and hvupdi_support lists + for(idx=0, ln=lfirst(dp.id); ln; ln=lnext(ln)) + dev_raw_dump(ldata(ln), strlen(ldata(ln))+1, id, "id", idx++); + for(idx=0, ln=lfirst(dp.usbpid); ln; ln=lnext(ln)) + dev_raw_dump(ldata(ln), sizeof(int), id, "usbpid", idx++); + for(idx=0, ln=lfirst(dp.hvupdi_support); ln; ln=lnext(ln)) + dev_raw_dump(ldata(ln), sizeof(int), id, "hvupdi_", idx++); + + // Dump cache_string values + if(dp.usbdev && *dp.usbdev) + dev_raw_dump(dp.usbdev, strlen(dp.usbdev)+1, id, "usbdev", 0); + if(dp.usbsn && *dp.usbsn) + dev_raw_dump(dp.usbsn, strlen(dp.usbsn)+1, id, "usbsn", 0); + if(dp.usbvendor && *dp.usbvendor) + dev_raw_dump(dp.usbvendor, strlen(dp.usbvendor)+1, id, "usbvend", 0); + if(dp.usbproduct && *dp.usbproduct) + dev_raw_dump(dp.usbproduct, strlen(dp.usbproduct)+1, id, "usbprod", 0); + + // Zap all bytes beyond terminating nul of desc, type and port array + if((len = strlen(dp.desc)+1) < sizeof dp.desc) + memset(dp.desc + len, 0, sizeof dp.desc - len); + if((len = strlen(dp.type)+1) < sizeof dp.type) + memset(dp.type + len, 0, sizeof dp.type - len); + if((len = strlen(dp.port)+1) < sizeof dp.port) + memset(dp.port + len, 0, sizeof dp.port - len); + + // Zap address values + dp.id = NULL; + dp.parent_id = NULL; + dp.initpgm = NULL; + + // Only dump contents of PROGRAMMER struct up to and excluding the fd component + dev_raw_dump((char *) &dp, offsetof(PROGRAMMER, fd), id, "pgm", 0); } @@ -934,7 +976,7 @@ void dev_output_pgm_defs(char *pgmid) { if((flags = strchr(pgmid, '/'))) *flags++ = 0; - if(!flags && !strcmp(pgmid, "*")) // treat -c * as if it was -c */A + if(!flags && !strcmp(pgmid, "*")) // Treat -c * as if it was -c */A flags = "A"; if(!*flags || !strchr("ASsrt", *flags)) { @@ -966,7 +1008,7 @@ void dev_output_pgm_defs(char *pgmid) { return; } - // redirect stderr to stdout + // Redirect stderr to stdout fflush(stderr); fflush(stdout); dup2(1, 2); astrc = !!strchr(flags, 'A'); diff --git a/src/libavrdude.h b/src/libavrdude.h index 7dcab3c2..2dc4bcc5 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -666,13 +666,13 @@ typedef enum { CONNTYPE_SPI } conntype_t; +/* Any changes here, please also reflect in dev_pgm_strct() of developer_opts.c */ typedef struct programmer_t { LISTID id; char desc[PGM_DESCLEN]; char type[PGM_TYPELEN]; char port[PGM_PORTLEN]; const char *parent_id; - void (*initpgm)(struct programmer_t * pgm); unsigned int pinno[N_PINS]; struct pindef_t pin[N_PINS]; exit_vcc_t exit_vcc; @@ -684,11 +684,16 @@ typedef struct programmer_t { int baudrate; int usbvid; LISTID usbpid; + LISTID hvupdi_support; // List of UPDI HV variants the tool supports, see HV_UPDI_VARIANT_x const char *usbdev, *usbsn, *usbvendor, *usbproduct; - double bitclock; /* JTAG ICE clock period in microseconds */ - int ispdelay; /* ISP clock delay */ + double bitclock; // JTAG ICE clock period in microseconds + int ispdelay; // ISP clock delay + int page_size; // Page size if the programmer supports paged write/load + + // Values below are not set by config_gram.y; first one must be fd for dev_pgm_raw() union filedescriptor fd; - int page_size; /* page size if the programmer supports paged write/load */ + void (*initpgm)(struct programmer_t * pgm); + int (*rdy_led) (struct programmer_t * pgm, int value); int (*err_led) (struct programmer_t * pgm, int value); int (*pgm_led) (struct programmer_t * pgm, int value); @@ -738,11 +743,10 @@ typedef struct programmer_t { int (*parseextparams) (struct programmer_t * pgm, LISTID xparams); void (*setup) (struct programmer_t * pgm); void (*teardown) (struct programmer_t * pgm); - const 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 */ - LISTID hvupdi_support; /* List of UPDI HV variants the tool supports. See HV_UPDI_VARIANT_ */ + const 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 } PROGRAMMER; #ifdef __cplusplus From 49fcd8a96e29db8ef7ed3a91197d4d18f8079f5b Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Mon, 8 Aug 2022 16:52:09 +0100 Subject: [PATCH 04/19] Implement -c */[sSA] (syntax-correct dump of programmer structure) --- src/avrpart.c | 2 +- src/config.c | 7 ++- src/config.h | 2 + src/config_gram.y | 3 +- src/developer_opts.c | 93 +++++++++++++++++++++++++++--- src/developer_opts_private.h | 16 ++++++ src/lexer.l | 15 +++-- src/libavrdude.h | 63 +++++++++++++------- src/main.c | 20 ++++--- src/pgm.c | 2 +- src/pgm_type.c | 108 +++++++++++++++++++---------------- src/pindefs.c | 45 ++++++++++++++- 12 files changed, 281 insertions(+), 95 deletions(-) diff --git a/src/avrpart.c b/src/avrpart.c index 970dfde8..c4a2bd8b 100644 --- a/src/avrpart.c +++ b/src/avrpart.c @@ -672,7 +672,7 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p, AVRPART * avr_new_part(void) { AVRPART * p; - char *nulp = cache_string(""); + const char *nulp = cache_string(""); p = (AVRPART *)malloc(sizeof(AVRPART)); if (p == NULL) { diff --git a/src/config.c b/src/config.c index 4308407e..34745daf 100644 --- a/src/config.c +++ b/src/config.c @@ -366,7 +366,7 @@ int read_config(const char * file) // Linear-search cache for a few often-referenced strings -char *cache_string(const char *file) { +const char *cache_string(const char *file) { static char **fnames; static int n=0; @@ -394,3 +394,8 @@ char *cache_string(const char *file) { return fnames[n++]; } + +// Captures comments during parsing +int capture_comment_char(int c) { + return c; +} diff --git a/src/config.h b/src/config.h index a7d2563d..1ebd2f70 100644 --- a/src/config.h +++ b/src/config.h @@ -101,6 +101,8 @@ void pyytext(void); char * dup_string(const char * str); +int capture_comment_char(int c); + #ifdef __cplusplus } #endif diff --git a/src/config_gram.y b/src/config_gram.y index 552832ec..c3554dcc 100644 --- a/src/config_gram.y +++ b/src/config_gram.y @@ -1397,7 +1397,8 @@ yesno : mem_specs : mem_spec TKN_SEMI | mem_alias TKN_SEMI | - mem_specs mem_spec TKN_SEMI + mem_specs mem_spec TKN_SEMI | + /* empty */ ; diff --git a/src/developer_opts.c b/src/developer_opts.c index 8d8c183c..bd59e940 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -613,8 +613,8 @@ void dev_output_part_defs(char *partdesc) { if((flags = strchr(partdesc, '/'))) *flags++ = 0; - if(!flags && !strcmp(partdesc, "*")) // Treat -p * as if it was -p */* - flags = "*"; + if(!flags && !strcmp(partdesc, "*")) // Treat -p * as if it was -p */s + flags = "s"; if(!*flags || !strchr("cdoASsrw*t", *flags)) { dev_info("%s: flags for developer option -p / not recognised\n", progname); @@ -640,7 +640,7 @@ void dev_output_part_defs(char *partdesc) { " $ avrdude -p m328*/st | grep chip_erase_delay\n" " avrdude -p*/r | sort\n" "Notes:\n" - " -p * is the same as -p */*\n" + " -p * is the same as -p */s\n" " This help message is printed using any unrecognised flag, eg, -p/h\n" " Leaving no space after -p can be an OK substitute for quoting in shells\n" " /s, /S and /A outputs are designed to be used as input in avrdude.conf\n" @@ -935,19 +935,37 @@ static void dev_pgm_raw(PROGRAMMER *pgm) { dp.id = NULL; dp.parent_id = NULL; dp.initpgm = NULL; + dp.usbpid = NULL; + dp.usbdev = NULL; + dp.usbsn = NULL; + dp.usbvendor = NULL; + dp.usbproduct = NULL; + dp.hvupdi_support = NULL; // Only dump contents of PROGRAMMER struct up to and excluding the fd component dev_raw_dump((char *) &dp, offsetof(PROGRAMMER, fd), id, "pgm", 0); } -static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) { - if(!tsv) { - int firstid = 1; +static const char *connstr(conntype_t conntype) { + switch(conntype) { + case CONNTYPE_PARALLEL: return "parallel"; + case CONNTYPE_SERIAL: return "serial"; + case CONNTYPE_USB: return "usb"; + case CONNTYPE_SPI: return "spi"; + default: return ""; + } +} +static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) { + char *id = ldata(lfirst(pgm->id)); + LNODEID ln; + int firstid; + + if(!tsv) { dev_info("#------------------------------------------------------------\n"); dev_info("# "); - for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) { + for(firstid=1, ln=lfirst(pgm->id); ln; ln=lnext(ln)) { if(!firstid) dev_info("/"); firstid = 0; @@ -961,6 +979,67 @@ static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) { dev_info("\nprogrammer\n"); } + if(tsv) + dev_info(".prog\t%s\tid\t", id); + else + dev_info(" %-19s = ", "id"); + for(firstid=1, ln=lfirst(pgm->id); ln; ln=lnext(ln)) { + if(!firstid) + dev_info(", "); + firstid = 0; + dev_info("\"%s\"", ldata(ln)); + } + dev_info(tsv? "\n": ";\n"); + + _if_pgmout(strcmp, "\"%s\"", desc); + _pgmout_fmt("type", "\"%s\"", locate_programmer_type_id(pgm->initpgm)); + _pgmout_fmt("connection_type", "%s", connstr(pgm->conntype)); + _if_pgmout(intcmp, "%d", baudrate); + + _if_pgmout(intcmp, "0x%04x", usbvid); + + if(pgm->usbpid && lfirst(pgm->usbpid)) { + if(tsv) + dev_info(".prog\t%s\tusbpid\t", id); + else + dev_info(" %-19s = ", "usbpid"); + for(firstid=1, ln=lfirst(pgm->usbpid); ln; ln=lnext(ln)) { + if(!firstid) + dev_info(", "); + firstid = 0; + dev_info("0x%04x", *(unsigned int *) ldata(ln)); + } + 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); + + for(int i=0; ipin+i); + if(str && *str) + _pgmout_fmt(avr_pin_lcname(i), "%s", str); + if(str) + free(str); + } + + if(pgm->hvupdi_support && lfirst(pgm->hvupdi_support)) { + if(tsv) + dev_info(".prog\t%s\thvupdu_support\t", id); + else + dev_info(" %-19s = ", "hvupdi_support"); + for(firstid=1, ln=lfirst(pgm->hvupdi_support); ln; ln=lnext(ln)) { + if(!firstid) + dev_info(", "); + firstid = 0; + dev_info("%d", *(unsigned int *) ldata(ln)); + } + dev_info(tsv? "\n": ";\n"); + } + + if(!tsv) dev_info(";\n"); } diff --git a/src/developer_opts_private.h b/src/developer_opts_private.h index 5a208199..e6be1ee9 100644 --- a/src/developer_opts_private.h +++ b/src/developer_opts_private.h @@ -51,6 +51,22 @@ static int dev_message(int msglvl, const char *fmt, ...); #define dev_notice(...) dev_message(DEV_NOTICE, __VA_ARGS__) #define dev_notice2(...) dev_message(DEV_NOTICE2, __VA_ARGS__) +#define _pgmout(fmt, component) \ + dev_part_strct_entry(tsv, ".prog", id, NULL, #component, dev_sprintf(fmt, pgm->component)) + +#define _pgmout_fmt(name, fmt, what) \ + dev_part_strct_entry(tsv, ".prog", id, NULL, name, dev_sprintf(fmt, what)) + +#define _if_pgmout(cmp, fmt, component) do { \ + if(!base || cmp(base->component, pgm->component)) \ + dev_part_strct_entry(tsv, ".prog", id, NULL, #component, dev_sprintf(fmt, pgm->component)); \ +} while(0) + +#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); \ +} while(0) + #define _partout(fmt, component) \ dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, dev_sprintf(fmt, p->component)) diff --git a/src/lexer.l b/src/lexer.l index 91d02597..c55d7853 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -67,13 +67,20 @@ SIGN [+-] -# { /* The following eats '#' style comments to end of line */ +# { /* The following captures all '#' style comments to end of line */ BEGIN(comment); } -[^\n] { /* eat comments */ } -\n { cfg_lineno++; BEGIN(INITIAL); } +[^\n]*\n+ { /* eat comments */ + capture_comment_char('#'); + for(int i=0; yytext[i]; i++) { + capture_comment_char(yytext[i]); + if(yytext[i] == '\n') + cfg_lineno++; + } + BEGIN(INITIAL); +} -"/*" { /* The following eats multiline C style comments */ +"/*" { /* The following eats multiline C style comments, they are not captured */ int c; int comment_start; diff --git a/src/libavrdude.h b/src/libavrdude.h index 2dc4bcc5..c17f611b 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -516,7 +516,15 @@ int pins_check(const struct programmer_t * const pgm, const struct pin_checklist const char * avr_pin_name(int pinname); /** - * This function returns a string representation of defined pins eg. ~1,2,~4,~5,7 + * Returns the name of the pin as lowercase string. + * + * @param pinname the pinname which we want as string. + * @returns a lowercase string with the pinname, or if pinname is invalid. + */ +const char * avr_pin_lcname(int pinname); + +/** + * This function returns a string of defined pins, eg, ~1,2,~4,~5,7 or " (not used)" * Another execution of this function will overwrite the previous result in the static buffer. * * @param[in] pindef the pin definition for which we want the string representation @@ -525,9 +533,17 @@ const char * avr_pin_name(int pinname); const char * pins_to_str(const struct pindef_t * const pindef); /** - * This function returns a string representation of pins in the mask eg. 1,3,5-7,9,12 + * 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) + */ +char *pins_to_strdup(const struct pindef_t * const pindef); + +/** + * This function returns a string representation of pins in the mask, eg, 1,3,5-7,9,12 * Another execution of this function will overwrite the previous result in the static buffer. - * Consecutive pin number are representated as start-end. + * Consecutive pin number are represented as start-end. * * @param[in] pinmask the pin mask for which we want the string representation * @returns pointer to a static string. @@ -670,29 +686,32 @@ typedef enum { typedef struct programmer_t { LISTID id; char desc[PGM_DESCLEN]; - char type[PGM_TYPELEN]; - char port[PGM_PORTLEN]; - const char *parent_id; - unsigned int pinno[N_PINS]; + void (*initpgm)(struct programmer_t *pgm); + const char *parent_id; // Used by developer options -c*/[sr...] struct pindef_t pin[N_PINS]; - exit_vcc_t exit_vcc; - exit_reset_t exit_reset; - exit_datahigh_t exit_datahigh; conntype_t conntype; - int ppidata; - int ppictrl; int baudrate; int usbvid; LISTID usbpid; - LISTID hvupdi_support; // List of UPDI HV variants the tool supports, see HV_UPDI_VARIANT_x - const char *usbdev, *usbsn, *usbvendor, *usbproduct; - double bitclock; // JTAG ICE clock period in microseconds - int ispdelay; // ISP clock delay - int page_size; // Page size if the programmer supports paged write/load + const char *usbdev; + const char *usbsn; + const char *usbvendor; + const char *usbproduct; + LISTID hvupdi_support; // List of UPDI HV variants the tool supports, see HV_UPDI_VARIANT_x - // Values below are not set by config_gram.y; first one must be fd for dev_pgm_raw() + // Values below are not set by config_gram.y; make sure fd is first for dev_pgm_raw() union filedescriptor fd; - void (*initpgm)(struct programmer_t * pgm); + char type[PGM_TYPELEN]; + char port[PGM_PORTLEN]; + unsigned int pinno[N_PINS]; // TODO to be removed if old pin data no longer needed + exit_vcc_t exit_vcc; // Should these be set in avrdude.conf? + exit_reset_t exit_reset; + exit_datahigh_t exit_datahigh; + int ppidata; + int ppictrl; + int ispdelay; // ISP clock delay + int page_size; // Page size if the programmer supports paged write/load + double bitclock; // JTAG ICE clock period in microseconds int (*rdy_led) (struct programmer_t * pgm, int value); int (*err_led) (struct programmer_t * pgm, int value); @@ -957,7 +976,9 @@ typedef struct programmer_type_t { extern "C" { #endif -const PROGRAMMER_TYPE * locate_programmer_type(/*LISTID programmer_types, */const char * id); +const PROGRAMMER_TYPE *locate_programmer_type(const char *id); + +const char *locate_programmer_type_id(const void (*initpgm)(struct programmer_t *pgm)); typedef void (*walk_programmer_types_cb)(const char *id, const char *desc, void *cookie); @@ -991,7 +1012,7 @@ void cleanup_config(void); int read_config(const char * file); -char *cache_string(const char *file); +const char *cache_string(const char *file); #ifdef __cplusplus } diff --git a/src/main.c b/src/main.c index 83bde3e9..ab10b4fa 100644 --- a/src/main.c +++ b/src/main.c @@ -752,13 +752,21 @@ int main(int argc, char * argv []) } - avrdude_message(MSG_NOTICE, "\n"); - + int dev_opts = 0; + // Developer option -c /[ASsrt] prints programmer description(s) and exits + if(programmer && (strcmp(programmer, "*") == 0 || strchr(programmer, '/'))) { + dev_output_pgm_defs(programmer); + dev_opts = 1; + } // Developer option -p /[dASsrcow*t] prints part description(s) and exits if(partdesc && (strcmp(partdesc, "*") == 0 || strchr(partdesc, '/'))) { dev_output_part_defs(partdesc); - exit(1); + dev_opts = 1; } + if(dev_opts) + exit(0); + + avrdude_message(MSG_NOTICE, "\n"); if (partdesc) { if (strcmp(partdesc, "?") == 0) { @@ -770,12 +778,6 @@ int main(int argc, char * argv []) } } - // Developer option -c /[ASsrt] prints programmer description(s) and exits - if(programmer && (strcmp(programmer, "*") == 0 || strchr(programmer, '/'))) { - dev_output_pgm_defs(programmer); - exit(1); - } - if (programmer) { if (strcmp(programmer, "?") == 0) { avrdude_message(MSG_INFO, "\n"); diff --git a/src/pgm.c b/src/pgm.c index a4e0ed54..238f61d8 100644 --- a/src/pgm.c +++ b/src/pgm.c @@ -65,7 +65,7 @@ PROGRAMMER * pgm_new(void) { int i; PROGRAMMER * pgm; - char *nulp = cache_string(""); + const char *nulp = cache_string(""); pgm = (PROGRAMMER *)malloc(sizeof(*pgm)); if (pgm == NULL) { diff --git a/src/pgm_type.c b/src/pgm_type.c index 82320fab..46090424 100644 --- a/src/pgm_type.c +++ b/src/pgm_type.c @@ -57,55 +57,55 @@ #include "xbee.h" -const PROGRAMMER_TYPE programmers_types[] = { - {"arduino", arduino_initpgm, arduino_desc}, - {"avr910", avr910_initpgm, avr910_desc}, - {"avrftdi", avrftdi_initpgm, avrftdi_desc}, - {"buspirate", buspirate_initpgm, buspirate_desc}, - {"buspirate_bb", buspirate_bb_initpgm, buspirate_bb_desc}, - {"butterfly", butterfly_initpgm, butterfly_desc}, - {"butterfly_mk", butterfly_mk_initpgm, butterfly_mk_desc}, - {"dragon_dw", jtagmkII_dragon_dw_initpgm, jtagmkII_dragon_dw_desc}, - {"dragon_hvsp", stk500v2_dragon_hvsp_initpgm, stk500v2_dragon_hvsp_desc}, - {"dragon_isp", stk500v2_dragon_isp_initpgm, stk500v2_dragon_isp_desc}, - {"dragon_jtag", jtagmkII_dragon_initpgm, jtagmkII_dragon_desc}, - {"dragon_pdi", jtagmkII_dragon_pdi_initpgm, jtagmkII_dragon_pdi_desc}, - {"dragon_pp", stk500v2_dragon_pp_initpgm, stk500v2_dragon_pp_desc}, - {"flip1", flip1_initpgm, flip1_desc}, - {"flip2", flip2_initpgm, flip2_desc}, - {"ftdi_syncbb", ft245r_initpgm, ft245r_desc}, - {"jtagmki", jtagmkI_initpgm, jtagmkI_desc}, - {"jtagmkii", jtagmkII_initpgm, jtagmkII_desc}, - {"jtagmkii_avr32", jtagmkII_avr32_initpgm, jtagmkII_avr32_desc}, - {"jtagmkii_dw", jtagmkII_dw_initpgm, jtagmkII_dw_desc}, - {"jtagmkii_isp", stk500v2_jtagmkII_initpgm, stk500v2_jtagmkII_desc}, - {"jtagmkii_pdi", jtagmkII_pdi_initpgm, jtagmkII_pdi_desc}, - {"jtagmkii_updi", jtagmkII_updi_initpgm, jtagmkII_updi_desc}, - {"jtagice3", jtag3_initpgm, jtag3_desc}, - {"jtagice3_pdi", jtag3_pdi_initpgm, jtag3_pdi_desc}, - {"jtagice3_updi", jtag3_updi_initpgm, jtag3_updi_desc}, - {"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc}, - {"jtagice3_isp", stk500v2_jtag3_initpgm, stk500v2_jtag3_desc}, - {"linuxgpio", linuxgpio_initpgm, linuxgpio_desc}, - {"linuxspi", linuxspi_initpgm, linuxspi_desc}, - {"micronucleus", micronucleus_initpgm, micronucleus_desc}, - {"par", par_initpgm, par_desc}, - {"pickit2", pickit2_initpgm, pickit2_desc}, - {"serbb", serbb_initpgm, serbb_desc}, - {"serialupdi", serialupdi_initpgm, serialupdi_desc}, - {"stk500", stk500_initpgm, stk500_desc}, - {"stk500generic", stk500generic_initpgm, stk500generic_desc}, - {"stk500v2", stk500v2_initpgm, stk500v2_desc}, - {"stk500hvsp", stk500hvsp_initpgm, stk500hvsp_desc}, - {"stk500pp", stk500pp_initpgm, stk500pp_desc}, - {"stk600", stk600_initpgm, stk600_desc}, - {"stk600hvsp", stk600hvsp_initpgm, stk600hvsp_desc}, - {"stk600pp", stk600pp_initpgm, stk600pp_desc}, - {"teensy", teensy_initpgm, teensy_desc}, - {"usbasp", usbasp_initpgm, usbasp_desc}, - {"usbtiny", usbtiny_initpgm, usbtiny_desc}, - {"wiring", wiring_initpgm, wiring_desc}, - {"xbee", xbee_initpgm, xbee_desc}, +const PROGRAMMER_TYPE programmers_types[] = { // Name(s) the programmers call themselves + {"arduino", arduino_initpgm, arduino_desc}, // "Arduino" + {"avr910", avr910_initpgm, avr910_desc}, // "avr910" + {"avrftdi", avrftdi_initpgm, avrftdi_desc}, // "avrftdi" + {"buspirate", buspirate_initpgm, buspirate_desc}, // "BusPirate" + {"buspirate_bb", buspirate_bb_initpgm, buspirate_bb_desc}, // "BusPirate_BB" + {"butterfly", butterfly_initpgm, butterfly_desc}, // "butterfly" + {"butterfly_mk", butterfly_mk_initpgm, butterfly_mk_desc}, // "butterfly_mk" + {"dragon_dw", jtagmkII_dragon_dw_initpgm, jtagmkII_dragon_dw_desc}, // "DRAGON_DW" + {"dragon_hvsp", stk500v2_dragon_hvsp_initpgm, stk500v2_dragon_hvsp_desc}, // "DRAGON_HVSP" + {"dragon_isp", stk500v2_dragon_isp_initpgm, stk500v2_dragon_isp_desc}, // "DRAGON_ISP" + {"dragon_jtag", jtagmkII_dragon_initpgm, jtagmkII_dragon_desc}, // "DRAGON_JTAG" + {"dragon_pdi", jtagmkII_dragon_pdi_initpgm, jtagmkII_dragon_pdi_desc}, // "DRAGON_PDI" + {"dragon_pp", stk500v2_dragon_pp_initpgm, stk500v2_dragon_pp_desc}, // "DRAGON_PP" + {"flip1", flip1_initpgm, flip1_desc}, // "flip1" + {"flip2", flip2_initpgm, flip2_desc}, // "flip2" + {"ftdi_syncbb", ft245r_initpgm, ft245r_desc}, // "ftdi_syncbb" + {"jtagmki", jtagmkI_initpgm, jtagmkI_desc}, // "JTAGMKI" + {"jtagmkii", jtagmkII_initpgm, jtagmkII_desc}, // "JTAGMKII" + {"jtagmkii_avr32", jtagmkII_avr32_initpgm, jtagmkII_avr32_desc}, // "JTAGMKII_AVR32" + {"jtagmkii_dw", jtagmkII_dw_initpgm, jtagmkII_dw_desc}, // "JTAGMKII_DW" + {"jtagmkii_isp", stk500v2_jtagmkII_initpgm, stk500v2_jtagmkII_desc}, // "JTAGMKII_ISP" + {"jtagmkii_pdi", jtagmkII_pdi_initpgm, jtagmkII_pdi_desc}, // "JTAGMKII_PDI" + {"jtagmkii_updi", jtagmkII_updi_initpgm, jtagmkII_updi_desc}, // "JTAGMKII_UPDI" + {"jtagice3", jtag3_initpgm, jtag3_desc}, // "JTAGICE3" + {"jtagice3_pdi", jtag3_pdi_initpgm, jtag3_pdi_desc}, // "JTAGICE3_PDI" + {"jtagice3_updi", jtag3_updi_initpgm, jtag3_updi_desc}, // "JTAGICE3_UPDI" + {"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc}, // "JTAGICE3_DW" + {"jtagice3_isp", stk500v2_jtag3_initpgm, stk500v2_jtag3_desc}, // "JTAG3_ISP" + {"linuxgpio", linuxgpio_initpgm, linuxgpio_desc}, // "linuxgpio" + {"linuxspi", linuxspi_initpgm, linuxspi_desc}, // LINUXSPI + {"micronucleus", micronucleus_initpgm, micronucleus_desc}, // "micronucleus" or "Micronucleus V2.0" + {"par", par_initpgm, par_desc}, // "PPI" + {"pickit2", pickit2_initpgm, pickit2_desc}, // "pickit2" + {"serbb", serbb_initpgm, serbb_desc}, // "SERBB" + {"serialupdi", serialupdi_initpgm, serialupdi_desc}, // "serialupdi" + {"stk500", stk500_initpgm, stk500_desc}, // "STK500" + {"stk500generic", stk500generic_initpgm, stk500generic_desc}, // "STK500GENERIC" + {"stk500v2", stk500v2_initpgm, stk500v2_desc}, // "STK500V2" + {"stk500hvsp", stk500hvsp_initpgm, stk500hvsp_desc}, // "STK500HVSP" + {"stk500pp", stk500pp_initpgm, stk500pp_desc}, // "STK500PP" + {"stk600", stk600_initpgm, stk600_desc}, // "STK600" + {"stk600hvsp", stk600hvsp_initpgm, stk600hvsp_desc}, // "STK600HVSP" + {"stk600pp", stk600pp_initpgm, stk600pp_desc}, // "STK600PP" + {"teensy", teensy_initpgm, teensy_desc}, // "teensy" + {"usbasp", usbasp_initpgm, usbasp_desc}, // "usbasp" + {"usbtiny", usbtiny_initpgm, usbtiny_desc}, // "USBtiny" or "usbtiny" + {"wiring", wiring_initpgm, wiring_desc}, // "Wiring" + {"xbee", xbee_initpgm, xbee_desc}, // "XBee" }; const PROGRAMMER_TYPE * locate_programmer_type(const char * id) @@ -128,6 +128,16 @@ const PROGRAMMER_TYPE * locate_programmer_type(const char * id) return NULL; } +// Return type id given the init function or "" if not found +const char *locate_programmer_type_id(void (*initpgm)(struct programmer_t *pgm)) { + for (int i=0; i < sizeof programmers_types/sizeof*programmers_types; i++) + if(programmers_types[i].initpgm == initpgm) + return programmers_types[i].id; + + return ""; +} + + /* * Iterate over the list of programmers given as "programmers", and * call the callback function cb for each entry found. cb is being diff --git a/src/pindefs.c b/src/pindefs.c index f51e5c20..1d860ebf 100644 --- a/src/pindefs.c +++ b/src/pindefs.c @@ -312,7 +312,7 @@ int pins_check(const struct programmer_t * const pgm, const struct pin_checklist } /** - * This function returns a string representation of defined pins eg. ~1,2,~4,~5,7 + * This function returns a string of defined pins, eg, ~1,2,~4,~5,7 or " (not used)" * Another execution of this function will overwrite the previous result in the static buffer. * * @param[in] pindef the pin definition for which we want the string representation @@ -346,6 +346,28 @@ const char * pins_to_str(const struct pindef_t * const pindef) { return buf; } +/** + * 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) + */ +char *pins_to_strdup(const struct pindef_t * const pindef) { + char buf[6*(PIN_MAX+1)], *p = buf; + + *buf = 0; + for(int pin = PIN_MIN; pin <= PIN_MAX; pin++) { + int index = pin / PIN_FIELD_ELEMENT_SIZE, bit = pin % PIN_FIELD_ELEMENT_SIZE; + if(pindef->mask[index] & (1 << bit)) { + if(*buf) + *p++ = ',', *p++=' '; + p += sprintf(p, "~%d" + !(pindef->inverse[index] & (1 << bit)), pin); + } + } + + return strdup(buf); +} + /** * Returns the name of the pin as string. * @@ -369,3 +391,24 @@ const char * avr_pin_name(int pinname) { } +/** + * Returns the name of the pin as string. + * + * @param pinname the pinname which we want as string. + * @returns a lowercase string with the pinname, or if pinname is invalid. + */ +const char * avr_pin_lcname(int pinname) { + switch(pinname) { + case PPI_AVR_VCC : return "vcc"; + case PPI_AVR_BUFF : return "buff"; + case PIN_AVR_RESET : return "reset"; + case PIN_AVR_SCK : return "sck"; + case PIN_AVR_MOSI : return "mosi"; + case PIN_AVR_MISO : return "miso"; + case PIN_LED_ERR : return "errled"; + case PIN_LED_RDY : return "rdyled"; + case PIN_LED_PGM : return "pgmled"; + case PIN_LED_VFY : return "vfyled"; + default : return ""; + } +} From f25bc5580634d6fee3d2d99409725c62a4af76f8 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Mon, 8 Aug 2022 17:03:06 +0100 Subject: [PATCH 05/19] Treat -c* the same as -c*/s --- src/developer_opts.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/developer_opts.c b/src/developer_opts.c index bd59e940..7e94aa15 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -1055,8 +1055,8 @@ void dev_output_pgm_defs(char *pgmid) { if((flags = strchr(pgmid, '/'))) *flags++ = 0; - if(!flags && !strcmp(pgmid, "*")) // Treat -c * as if it was -c */A - flags = "A"; + if(!flags && !strcmp(pgmid, "*")) // Treat -c * as if it was -c */s + flags = "s"; if(!*flags || !strchr("ASsrt", *flags)) { dev_info("%s: flags for developer option -c / not recognised\n", progname); @@ -1077,7 +1077,7 @@ void dev_output_pgm_defs(char *pgmid) { " $ avrdude -c */st | grep baudrate\n" " $ avrdude -c */r | sort\n" "Notes:\n" - " -c * is the same as -c */A\n" + " -c * is the same as -c */s\n" " This help message is printed using any unrecognised flag, eg, -c/h\n" " Leaving no space after -c can be an OK substitute for quoting in shells\n" " /s, /S and /A outputs are designed to be used as input in avrdude.conf\n" From 1da97f6825ed79db849d2aebf63a209e69e7ecc0 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Mon, 8 Aug 2022 17:21:21 +0100 Subject: [PATCH 06/19] Adjust declaration of locate_programmer_type_id() to definition --- src/libavrdude.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libavrdude.h b/src/libavrdude.h index c17f611b..9ab1a8d9 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -978,7 +978,7 @@ extern "C" { const PROGRAMMER_TYPE *locate_programmer_type(const char *id); -const char *locate_programmer_type_id(const void (*initpgm)(struct programmer_t *pgm)); +const char *locate_programmer_type_id(void (*initpgm)(struct programmer_t *pgm)); typedef void (*walk_programmer_types_cb)(const char *id, const char *desc, void *cookie); From c21be27a7d7c0a6096e452db58cc10b8a71462aa Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Mon, 8 Aug 2022 17:27:38 +0100 Subject: [PATCH 07/19] Replace const char array indexing with equivalent code in pindefs.c --- src/pindefs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pindefs.c b/src/pindefs.c index 1d860ebf..625d1f18 100644 --- a/src/pindefs.c +++ b/src/pindefs.c @@ -361,7 +361,7 @@ char *pins_to_strdup(const struct pindef_t * const pindef) { if(pindef->mask[index] & (1 << bit)) { if(*buf) *p++ = ',', *p++=' '; - p += sprintf(p, "~%d" + !(pindef->inverse[index] & (1 << bit)), pin); + p += sprintf(p, pindef->inverse[index] & (1 << bit)? "~%d": "%d", pin); } } From 7c8d336e27485cf4d8055eb4221befa185932711 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Tue, 9 Aug 2022 09:23:26 +0100 Subject: [PATCH 08/19] Change dev_info() to stdout and no longer redirect stderr to stdout --- src/developer_opts.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/developer_opts.c b/src/developer_opts.c index 7e94aa15..de245608 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -214,7 +214,7 @@ int dev_message(int msglvl, const char *fmt, ...) { if(verbose >= msglvl) { va_start(ap, fmt); - rc = vfprintf(stderr, fmt, ap); + rc = vfprintf(stdout, fmt, ap); va_end(ap); if(rc > 0) dev_nprinted += rc; @@ -651,9 +651,6 @@ void dev_output_part_defs(char *partdesc) { return; } - // Redirect stderr to stdout - fflush(stderr); fflush(stdout); dup2(1, 2); - all = *flags == '*'; cmdok = all || !!strchr(flags, 'c'); descs = all || !!strchr(flags, 'd'); @@ -1087,9 +1084,6 @@ void dev_output_pgm_defs(char *pgmid) { return; } - // Redirect stderr to stdout - fflush(stderr); fflush(stdout); dup2(1, 2); - astrc = !!strchr(flags, 'A'); strct = !!strchr(flags, 'S'); cmpst = !!strchr(flags, 's'); From 8a717987ec1cdb9612fec4d42cdd1ec4165b1489 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Tue, 9 Aug 2022 13:19:40 +0100 Subject: [PATCH 09/19] Change unsigned short eecr; to unsigned char eecr; in libavrdude's AVRPART --- src/developer_opts.c | 2 +- src/libavrdude.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/developer_opts.c b/src/developer_opts.c index de245608..b4f69753 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -533,7 +533,7 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) { _if_partout(intcmp, "0x%02x", idr); _if_partout(intcmp, "0x%02x", rampz); _if_partout(intcmp, "0x%02x", spmcr); - _if_partout(intcmp, "0x%02x", eecr); // Why is eecr an unsigned short? + _if_partout(intcmp, "0x%02x", eecr); _if_partout(intcmp, "0x%04x", mcu_base); _if_partout(intcmp, "0x%04x", nvm_base); _if_partout(intcmp, "0x%04x", ocd_base); diff --git a/src/libavrdude.h b/src/libavrdude.h index 9ab1a8d9..fb4a53dd 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -270,7 +270,7 @@ typedef struct avrpart { unsigned char idr; /* JTAG ICE mkII XML file parameter */ unsigned char rampz; /* JTAG ICE mkII XML file parameter */ unsigned char spmcr; /* JTAG ICE mkII XML file parameter */ - unsigned short eecr; /* JTAC ICE mkII XML file parameter */ + unsigned char eecr; /* JTAC ICE mkII XML file parameter */ unsigned int mcu_base; /* Base address of MCU control block in ATxmega devices */ unsigned int nvm_base; /* Base address of NVM controller in ATxmega devices */ unsigned int ocd_base; /* Base address of OCD module in AVR8X/UPDI devices */ From 22c4dbf23e89e16491b76dceadfc443eca1c56bc Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Tue, 9 Aug 2022 21:20:44 +0100 Subject: [PATCH 10/19] 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). --- src/avr.c | 2 +- src/avrpart.c | 6 +- src/config.c | 338 ++++++++++++++++++++++++++--------- src/config.h | 29 ++- src/config_gram.y | 18 +- src/developer_opts.c | 51 +++--- src/developer_opts_private.h | 15 +- src/lexer.l | 28 ++- src/libavrdude.h | 12 +- src/main.c | 5 +- src/pgm.c | 24 +-- src/pindefs.c | 4 +- src/term.c | 175 +----------------- src/update.c | 50 ++---- 14 files changed, 355 insertions(+), 402 deletions(-) diff --git a/src/avr.c b/src/avr.c index eea0ad8a..62760ce7 100644 --- a/src/avr.c +++ b/src/avr.c @@ -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; } } diff --git a/src/avrpart.c b/src/avrpart.c index c4a2bd8b..40baa449 100644 --- a/src/avrpart.c +++ b/src/avrpart.c @@ -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); } diff --git a/src/config.c b/src/config.c index 34745daf..8d99848d 100644 --- a/src/config.c +++ b/src/config.c @@ -25,6 +25,7 @@ #include #include #include +#include #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; +} diff --git a/src/config.h b/src/config.h index 1ebd2f70..260d404a 100644 --- a/src/config.h +++ b/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,41 +66,36 @@ 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 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, ...); -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); -char * dup_string(const char * str); - int capture_comment_char(int c); #ifdef __cplusplus diff --git a/src/config_gram.y b/src/config_gram.y index c3554dcc..0b9cf6cd 100644 --- a/src/config_gram.y +++ b/src/config_gram.y @@ -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 diff --git a/src/developer_opts.c b/src/developer_opts.c index b4f69753..6cbfa4f2 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -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,13 +988,16 @@ 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)); - _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, "0x%04x", usbvid); @@ -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; ipin+i); diff --git a/src/developer_opts_private.h b/src/developer_opts_private.h index e6be1ee9..a5c1562e 100644 --- a/src/developer_opts_private.h +++ b/src/developer_opts_private.h @@ -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) diff --git a/src/lexer.l b/src/lexer.l index c55d7853..23fd2277 100644 --- a/src/lexer.l +++ b/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); } [^\n]*\n+ { /* eat comments */ @@ -107,20 +113,6 @@ SIGN [+-] } -\" { *string_buf_ptr = 0; string_buf_ptr = string_buf; - yylval = string(string_buf_ptr); BEGIN(INITIAL); return TKN_STRING; } -\\n *string_buf_ptr++ = '\n'; -\\t *string_buf_ptr++ = '\t'; -\\r *string_buf_ptr++ = '\r'; -\\b *string_buf_ptr++ = '\b'; -\\f *string_buf_ptr++ = '\f'; -\\(.|\n) *(string_buf_ptr++) = yytext[1]; -[^\\\n\"]+ { char *yptr = yytext; while (*yptr) - *(string_buf_ptr++) = *(yptr++); } - -\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; } diff --git a/src/libavrdude.h b/src/libavrdude.h index fb4a53dd..840d8fc1 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -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 diff --git a/src/main.c b/src/main.c index ab10b4fa..b696d6d7 100644 --- a/src/main.c +++ b/src/main.c @@ -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)) { diff --git a/src/pgm.c b/src/pgm.c index 238f61d8..07cbed57 100644 --- a/src/pgm.c +++ b/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); } diff --git a/src/pindefs.c b/src/pindefs.c index 625d1f18..2e78c8df 100644 --- a/src/pindefs.c +++ b/src/pindefs.c @@ -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); } /** diff --git a/src/term.c b/src/term.c index f02f95c5..672a09cd 100644 --- a/src/term.c +++ b/src/term.c @@ -20,7 +20,6 @@ #include "ac_cfg.h" -#include #include #include #include @@ -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", diff --git a/src/update.c b/src/update.c index 2aa2579b..972c3847 100644 --- a/src/update.c +++ b/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; From 7375477f7097b4cb835f4e17889fc0674bb1ed38 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Tue, 9 Aug 2022 21:45:04 +0100 Subject: [PATCH 11/19] Replace string arrays with const char * and allocated space (part 1) This commit deals with default_programmer, default_serial, default_parallel and default_spi. The long term objective is to remove all fixed-size buffers from the structures that lexer.l and config_gram.y deal with. --- src/config.c | 8 ++++---- src/config.h | 2 -- src/config_gram.y | 12 ++++-------- src/libavrdude.h | 8 ++++---- src/main.c | 17 +++++++++-------- 5 files changed, 21 insertions(+), 26 deletions(-) diff --git a/src/config.c b/src/config.c index 8d99848d..f0b65822 100644 --- a/src/config.c +++ b/src/config.c @@ -33,10 +33,10 @@ #include "config_gram.h" -char default_programmer[MAX_STR_CONST]; -char default_parallel[PATH_MAX]; -char default_serial[PATH_MAX]; -char default_spi[PATH_MAX]; +const char *default_programmer; +const char *default_parallel; +const char *default_serial; +const char *default_spi; double default_bitclock; LISTID string_list; diff --git a/src/config.h b/src/config.h index 260d404a..7b6c6d0d 100644 --- a/src/config.h +++ b/src/config.h @@ -30,8 +30,6 @@ #endif -#define MAX_STR_CONST 1024 - enum { V_NONE, V_NUM, V_NUM_REAL, V_STR }; typedef struct value_t { int type; diff --git a/src/config_gram.y b/src/config_gram.y index 0b9cf6cd..554de900 100644 --- a/src/config_gram.y +++ b/src/config_gram.y @@ -246,26 +246,22 @@ def : part_def TKN_SEMI | K_DEFAULT_PROGRAMMER TKN_EQUAL TKN_STRING TKN_SEMI { - strncpy(default_programmer, $3->value.string, MAX_STR_CONST); - default_programmer[MAX_STR_CONST-1] = 0; + default_programmer = cache_string($3->value.string); free_token($3); } | K_DEFAULT_PARALLEL TKN_EQUAL TKN_STRING TKN_SEMI { - strncpy(default_parallel, $3->value.string, PATH_MAX); - default_parallel[PATH_MAX-1] = 0; + default_parallel = cache_string($3->value.string); free_token($3); } | K_DEFAULT_SERIAL TKN_EQUAL TKN_STRING TKN_SEMI { - strncpy(default_serial, $3->value.string, PATH_MAX); - default_serial[PATH_MAX-1] = 0; + default_serial = cache_string($3->value.string); free_token($3); } | K_DEFAULT_SPI TKN_EQUAL TKN_STRING TKN_SEMI { - strncpy(default_spi, $3->value.string, PATH_MAX); - default_spi[PATH_MAX-1] = 0; + default_spi = cache_string($3->value.string); free_token($3); } | diff --git a/src/libavrdude.h b/src/libavrdude.h index 840d8fc1..3c2f2a57 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -992,10 +992,10 @@ void walk_programmer_types(/*LISTID programmer_types,*/ walk_programmer_types_cb extern LISTID part_list; extern LISTID programmers; -extern char default_programmer[]; -extern char default_parallel[]; -extern char default_serial[]; -extern char default_spi[]; +extern const char *default_programmer; +extern const char *default_parallel; +extern const char *default_serial; +extern const char *default_spi; extern double default_bitclock; /* This name is fixed, it's only here for symmetry with diff --git a/src/main.c b/src/main.c index b696d6d7..08266f00 100644 --- a/src/main.c +++ b/src/main.c @@ -314,10 +314,11 @@ int main(int argc, char * argv []) else progname = argv[0]; - default_parallel[0] = 0; - default_serial[0] = 0; - default_spi[0] = 0; - default_bitclock = 0.0; + default_programmer = ""; + default_parallel = ""; + default_serial = ""; + default_spi = ""; + default_bitclock = 0.0; init_config(); @@ -351,7 +352,7 @@ int main(int argc, char * argv []) quell_progress = 0; exitspecs = NULL; pgm = NULL; - programmer = default_programmer; + programmer = cfg_strdup("main()", default_programmer); verbose = 0; baudrate = 0; bitclock = 0.0; @@ -755,7 +756,7 @@ int main(int argc, char * argv []) int dev_opts = 0; // Developer option -c /[ASsrt] prints programmer description(s) and exits if(programmer && (strcmp(programmer, "*") == 0 || strchr(programmer, '/'))) { - dev_output_pgm_defs(programmer); + dev_output_pgm_defs(cfg_strdup("main()", programmer)); dev_opts = 1; } // Developer option -p /[dASsrcow*t] prints part description(s) and exits @@ -849,11 +850,11 @@ int main(int argc, char * argv []) switch (pgm->conntype) { case CONNTYPE_PARALLEL: - port = default_parallel; + port = cfg_strdup("main()", default_parallel); break; case CONNTYPE_SERIAL: - port = default_serial; + port = cfg_strdup("main()", default_serial); break; case CONNTYPE_USB: From f4c5a8350d9c13aef4c2d085ca9fc9be3b570b46 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Wed, 10 Aug 2022 16:14:56 +0100 Subject: [PATCH 12/19] Replace string arrays with const char * and allocated space (part 2) This commit replaces fixed-string buffers in PROGRAMMER, AVRPART and AVRMEM that are dealt with by the parser and grammar. Now, string assignments are always to const char *, ie, these are read-only strings with arbitrary length. config_gram.y now only needs to consider one type of string assignment. This commit also - Replaces the simple linear-search cache_string() function with faster hashed cache_string(). Either way, the returned value is likely to be shared, so should never be free()'d. - Duplicates hvupdi_support list in pgm_dup() and frees it in pgm_free() - Adds const qualifier to some function args in avrpart.c and pgm.c - Hardens some functions against being called with NULL pointers - Ensures _new() and _dup() functions for parts, programmers and memory return a suitable memory. Out of memory triggers exit in one of three functions, cfg_malloc(), cfg_realloc() and cfg_strdup(); there is rarely anything useful that AVRDUDE or, for that matter, any application compiled against libavrdude can do once you run out of memory as AVRDUDE/libavrdude rely heavily on allocation of memory. --- src/avrpart.c | 408 ++++++++++++++++--------------------------- src/config.c | 71 +++++--- src/config.h | 2 +- src/config_gram.y | 54 +----- src/developer_opts.c | 59 ++++--- src/jtagmkI.c | 2 +- src/jtagmkII.c | 2 +- src/lexer.l | 10 +- src/libavrdude.h | 56 +++--- src/main.c | 10 +- src/pgm.c | 137 +++++++-------- src/pickit2.c | 20 ++- src/update.c | 10 +- 13 files changed, 359 insertions(+), 482 deletions(-) diff --git a/src/avrpart.c b/src/avrpart.c index 40baa449..526d0503 100644 --- a/src/avrpart.c +++ b/src/avrpart.c @@ -1,4 +1,3 @@ - /* * avrdude - A Downloader/Uploader for AVR device programmers * Copyright (C) 2000-2004 Brian S. Dean @@ -31,44 +30,23 @@ *** Elementary functions dealing with OPCODE structures ***/ -OPCODE * avr_new_opcode(void) -{ - OPCODE * m; - - m = (OPCODE *)malloc(sizeof(*m)); - if (m == NULL) { - avrdude_message(MSG_INFO, "avr_new_opcode(): out of memory\n"); - exit(1); - } - - memset(m, 0, sizeof(*m)); - - return m; +OPCODE *avr_new_opcode(void) { + return (OPCODE *) cfg_malloc("avr_new_opcode()", sizeof(OPCODE)); } -static OPCODE * avr_dup_opcode(OPCODE * op) -{ - OPCODE * m; - - /* this makes life easier */ - if (op == NULL) { +static OPCODE *avr_dup_opcode(const OPCODE *op) { + if(op == NULL) // Caller wants NULL if op == NULL return NULL; - } - - m = (OPCODE *)malloc(sizeof(*m)); - if (m == NULL) { - avrdude_message(MSG_INFO, "avr_dup_opcode(): out of memory\n"); - exit(1); - } + OPCODE *m = (OPCODE *) cfg_malloc("avr_dup_opcode()", sizeof(*m)); memcpy(m, op, sizeof(*m)); return m; } -void avr_free_opcode(OPCODE * op) -{ - free(op); +void avr_free_opcode(OPCODE *op) { + if(op) + free(op); } @@ -268,11 +246,10 @@ int avr_set_input(OPCODE * op, unsigned char * cmd, unsigned char data) /* * avr_get_output() * - * Retreive output data bits from the command results based on the + * Retrieve output data bits from the command results based on the * opcode data. */ -int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data) -{ +int avr_get_output(const OPCODE *op, const unsigned char *res, unsigned char *data) { int i, j, bit; unsigned char value; unsigned char mask; @@ -301,8 +278,7 @@ int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data) * Calculate the byte number of the output data based on the * opcode data. */ -int avr_get_output_index(OPCODE * op) -{ +int avr_get_output_index(const OPCODE *op) { int i, j; for (i=0; i<32; i++) { @@ -353,34 +329,17 @@ static char * bittype(int type) *** Elementary functions dealing with AVRMEM structures ***/ -AVRMEM * avr_new_memtype(void) -{ - AVRMEM * m; - - m = (AVRMEM *)malloc(sizeof(*m)); - if (m == NULL) { - avrdude_message(MSG_INFO, "avr_new_memtype(): out of memory\n"); - exit(1); - } - - memset(m, 0, sizeof(*m)); +AVRMEM *avr_new_memtype(void) { + AVRMEM *m = (AVRMEM *) cfg_malloc("avr_new_memtype()", sizeof(*m)); + m->desc = cache_string(""); m->page_size = 1; // ensure not 0 return m; } -AVRMEM_ALIAS * avr_new_memalias(void) -{ - AVRMEM_ALIAS * m; - - m = (AVRMEM_ALIAS *)malloc(sizeof(*m)); - if (m == NULL) { - avrdude_message(MSG_INFO, "avr_new_memalias(): out of memory\n"); - exit(1); - } - - memset(m, 0, sizeof(*m)); - +AVRMEM_ALIAS *avr_new_memalias(void) { + AVRMEM_ALIAS *m = (AVRMEM_ALIAS *) cfg_malloc("avr_new_memalias()", sizeof*m); + m->desc = cache_string(""); return m; } @@ -389,106 +348,79 @@ AVRMEM_ALIAS * avr_new_memalias(void) * Allocate and initialize memory buffers for each of the device's * defined memory regions. */ -int avr_initmem(AVRPART * p) -{ - LNODEID ln; - AVRMEM * m; +int avr_initmem(const AVRPART *p) { + if(p == NULL || p->mem == NULL) + return -1; - for (ln=lfirst(p->mem); ln; ln=lnext(ln)) { - m = ldata(ln); - m->buf = (unsigned char *) malloc(m->size); - if (m->buf == NULL) { - avrdude_message(MSG_INFO, "%s: can't alloc buffer for %s size of %d bytes\n", - progname, m->desc, m->size); - return -1; - } - m->tags = (unsigned char *) malloc(m->size); - if (m->tags == NULL) { - avrdude_message(MSG_INFO, "%s: can't alloc buffer for %s size of %d bytes\n", - progname, m->desc, m->size); - return -1; - } + for (LNODEID ln=lfirst(p->mem); ln; ln=lnext(ln)) { + AVRMEM *m = ldata(ln); + m->buf = (unsigned char *) cfg_malloc("avr_initmem()", m->size); + m->tags = (unsigned char *) cfg_malloc("avr_initmem()", m->size); } return 0; } -AVRMEM * avr_dup_mem(AVRMEM * m) -{ - AVRMEM * n; - int i; +AVRMEM *avr_dup_mem(const AVRMEM *m) { + AVRMEM *n = avr_new_memtype(); - n = avr_new_memtype(); + if(m) { + *n = *m; - *n = *m; - - if (m->buf != NULL) { - n->buf = (unsigned char *)malloc(n->size); - if (n->buf == NULL) { - avrdude_message(MSG_INFO, "avr_dup_mem(): out of memory (memsize=%d)\n", - n->size); - exit(1); + if(m->buf) { + n->buf = (unsigned char *) cfg_malloc("avr_dup_mem()", n->size); + memcpy(n->buf, m->buf, n->size); } - memcpy(n->buf, m->buf, n->size); - } - if (m->tags != NULL) { - n->tags = (unsigned char *)malloc(n->size); - if (n->tags == NULL) { - avrdude_message(MSG_INFO, "avr_dup_mem(): out of memory (memsize=%d)\n", - n->size); - exit(1); + if(m->tags) { + n->tags = (unsigned char *) cfg_malloc("avr_dup_mem()", n->size); + memcpy(n->tags, m->tags, n->size); } - memcpy(n->tags, m->tags, n->size); - } - for (i = 0; i < AVR_OP_MAX; i++) { - n->op[i] = avr_dup_opcode(n->op[i]); + for(int i = 0; i < AVR_OP_MAX; i++) + n->op[i] = avr_dup_opcode(n->op[i]); } return n; } -AVRMEM_ALIAS * avr_dup_memalias(AVRMEM_ALIAS * m) -{ - AVRMEM_ALIAS * n; +AVRMEM_ALIAS *avr_dup_memalias(const AVRMEM_ALIAS *m) { + AVRMEM_ALIAS *n = avr_new_memalias(); - n = avr_new_memalias(); - - *n = *m; + if(m) + *n = *m; return n; } -void avr_free_mem(AVRMEM * m) -{ - if (m->buf != NULL) { - free(m->buf); - m->buf = NULL; - } - if (m->tags != NULL) { - free(m->tags); - m->tags = NULL; - } - for(size_t i=0; iop)/sizeof(m->op[0]); i++) - { - if (m->op[i] != NULL) - { - avr_free_opcode(m->op[i]); - m->op[i] = NULL; - } - } - free(m); -} +void avr_free_mem(AVRMEM * m) { + if(m == NULL) + return; -void avr_free_memalias(AVRMEM_ALIAS * m) -{ + if(m->buf) { + free(m->buf); + m->buf = NULL; + } + if(m->tags) { + free(m->tags); + m->tags = NULL; + } + for(size_t i=0; iop)/sizeof(m->op[0]); i++) { + if(m->op[i]) { + avr_free_opcode(m->op[i]); + m->op[i] = NULL; + } + } free(m); } -AVRMEM_ALIAS * avr_locate_memalias(AVRPART * p, const char * desc) -{ +void avr_free_memalias(AVRMEM_ALIAS *m) { + if(m) + free(m); +} + +AVRMEM_ALIAS *avr_locate_memalias(const AVRPART *p, const char *desc) { AVRMEM_ALIAS * m, * match; LNODEID ln; int matches; @@ -514,8 +446,7 @@ AVRMEM_ALIAS * avr_locate_memalias(AVRPART * p, const char * desc) return NULL; } -AVRMEM * avr_locate_mem_noalias(AVRPART * p, const char * desc) -{ +AVRMEM *avr_locate_mem_noalias(const AVRPART *p, const char *desc) { AVRMEM * m, * match; LNODEID ln; int matches; @@ -542,8 +473,7 @@ AVRMEM * avr_locate_mem_noalias(AVRPART * p, const char * desc) } -AVRMEM * avr_locate_mem(AVRPART * p, const char * desc) -{ +AVRMEM *avr_locate_mem(const AVRPART *p, const char *desc) { AVRMEM * m, * match; AVRMEM_ALIAS * alias; LNODEID ln; @@ -577,24 +507,20 @@ AVRMEM * avr_locate_mem(AVRPART * p, const char * desc) return NULL; } -AVRMEM_ALIAS * avr_find_memalias(AVRPART * p, AVRMEM * m_orig) -{ - AVRMEM_ALIAS * m; - LNODEID ln; - - for (ln=lfirst(p->mem_alias); ln; ln=lnext(ln)) { - m = ldata(ln); - if (m->aliased_mem == m_orig) - return m; - } +AVRMEM_ALIAS *avr_find_memalias(const AVRPART *p, const AVRMEM *m_orig) { + if(p && p->mem_alias && m_orig) + for(LNODEID ln=lfirst(p->mem_alias); ln; ln=lnext(ln)) { + AVRMEM_ALIAS *m = ldata(ln); + if(m->aliased_mem == m_orig) + return m; + } return NULL; } -void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p, - int type, int verbose) -{ +void avr_mem_display(const char *prefix, FILE *f, const AVRMEM *m, + const AVRPART *p, int verbose) { static unsigned int prev_mem_offset; static int prev_mem_size; int i, j; @@ -623,7 +549,7 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p, AVRMEM_ALIAS *ap = avr_find_memalias(p, m); /* Show alias if the current and the next memory section has the same offset and size, we're not out of band and a family_id is present */ - char * mem_desc_alias = ap? ap->desc: ""; + const char *mem_desc_alias = ap? ap->desc: ""; fprintf(f, "%s%-11s %-8s %4d %5d %5d %4d %-6s %6d %4d %6d %5d %5d 0x%02x 0x%02x\n", prefix, @@ -669,74 +595,63 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p, * Elementary functions dealing with AVRPART structures */ -AVRPART * avr_new_part(void) -{ - AVRPART * p; +AVRPART *avr_new_part(void) { + AVRPART *p = (AVRPART *) cfg_malloc("avr_new_part()", sizeof(AVRPART)); const char *nulp = cache_string(""); - p = (AVRPART *)malloc(sizeof(AVRPART)); - if (p == NULL) { - avrdude_message(MSG_INFO, "new_part(): out of memory\n"); - exit(1); - } - memset(p, 0, sizeof(*p)); - p->id[0] = 0; - p->desc[0] = 0; + // Initialise const char * and LISTID entities + p->desc = nulp; + p->id = nulp; + p->parent_id = nulp; + p->family_id = nulp; + p->config_file = nulp; + p->mem = lcreat(NULL, 0); + p->mem_alias = lcreat(NULL, 0); + + // Default values + p->hvupdi_variant = -1; + memset(p->signature, 0xFF, 3); p->reset_disposition = RESET_DEDICATED; p->retry_pulse = PIN_AVR_SCK; p->flags = AVRPART_SERIALOK | AVRPART_PARALLELOK | AVRPART_ENABLEPAGEPROGRAMMING; - p->parent_id = nulp; - p->config_file = nulp; - p->lineno = 0; - memset(p->signature, 0xFF, 3); p->ctl_stack_type = CTL_STACK_NONE; p->ocdrev = -1; - p->hvupdi_variant = -1; - - p->mem = lcreat(NULL, 0); - p->mem_alias = lcreat(NULL, 0); + p->lineno = 0; return p; } -AVRPART * avr_dup_part(AVRPART * d) -{ - AVRPART * p; - LISTID save, save2; - LNODEID ln, ln2; - int i; +AVRPART *avr_dup_part(const AVRPART *d) { + AVRPART *p = avr_new_part(); - p = avr_new_part(); - save = p->mem; - save2 = p->mem_alias; + if(d) { + *p = *d; - *p = *d; + // Duplicate the memory and alias chains + p->mem = lcreat(NULL, 0); + p->mem_alias = lcreat(NULL, 0); - p->mem = save; - p->mem_alias = save2; - for (ln=lfirst(d->mem); ln; ln=lnext(ln)) { - AVRMEM *m = ldata(ln); - AVRMEM *m2 = avr_dup_mem(m); - ladd(p->mem, m2); - // see if there is any alias for it - for (ln2=lfirst(d->mem_alias); ln2; ln2=lnext(ln2)) { - AVRMEM_ALIAS *a = ldata(ln2); - if (a->aliased_mem == m) { - // yes, duplicate it - AVRMEM_ALIAS *a2 = avr_dup_memalias(a); - // ... adjust the pointer ... - a2->aliased_mem = m2; - // ... and add to new list - ladd(p->mem_alias, a2); + for(LNODEID ln=lfirst(d->mem); ln; ln=lnext(ln)) { + AVRMEM *m = ldata(ln); + AVRMEM *m2 = avr_dup_mem(m); + ladd(p->mem, m2); + // See if there is any alias for it + for(LNODEID ln2=lfirst(d->mem_alias); ln2; ln2=lnext(ln2)) { + AVRMEM_ALIAS *a = ldata(ln2); + if (a->aliased_mem == m) { + // Yes, duplicate it, adjust the pointer and add to new list + AVRMEM_ALIAS *a2 = avr_dup_memalias(a); + a2->aliased_mem = m2; + ladd(p->mem_alias, a2); + } } } - } - for (i = 0; i < AVR_OP_MAX; i++) { - p->op[i] = avr_dup_opcode(p->op[i]); + for(int i = 0; i < AVR_OP_MAX; i++) + p->op[i] = avr_dup_opcode(p->op[i]); } return p; @@ -758,61 +673,45 @@ void avr_free_part(AVRPART * d) free(d); } -AVRPART * locate_part(LISTID parts, const char * partdesc) -{ - LNODEID ln1; +AVRPART *locate_part(const LISTID parts, const char *partdesc) { AVRPART * p = NULL; - int found; + int found = 0; if(!parts || !partdesc) return NULL; - found = 0; - - for (ln1=lfirst(parts); ln1 && !found; ln1=lnext(ln1)) { + for (LNODEID ln1=lfirst(parts); ln1 && !found; ln1=lnext(ln1)) { p = ldata(ln1); if ((strcasecmp(partdesc, p->id) == 0) || (strcasecmp(partdesc, p->desc) == 0)) found = 1; } - if (found) - return p; - - return NULL; + return found? p: NULL; } -AVRPART * locate_part_by_avr910_devcode(LISTID parts, int devcode) -{ - LNODEID ln1; - AVRPART * p = NULL; - - for (ln1=lfirst(parts); ln1; ln1=lnext(ln1)) { - p = ldata(ln1); - if (p->avr910_devcode == devcode) - return p; - } - - return NULL; -} - -AVRPART * locate_part_by_signature(LISTID parts, unsigned char * sig, - int sigsize) -{ - LNODEID ln1; - AVRPART * p = NULL; - int i; - - if (sigsize == 3) { - for (ln1=lfirst(parts); ln1; ln1=lnext(ln1)) { - p = ldata(ln1); - for (i=0; i<3; i++) - if (p->signature[i] != sig[i]) - break; - if (i == 3) +AVRPART *locate_part_by_avr910_devcode(const LISTID parts, int devcode) { + if(parts) + for (LNODEID ln1=lfirst(parts); ln1; ln1=lnext(ln1)) { + AVRPART * p = ldata(ln1); + if (p->avr910_devcode == devcode) + return p; + } + + return NULL; +} + +AVRPART *locate_part_by_signature(const LISTID parts, unsigned char *sig, int sigsize) { + if(parts && sigsize == 3) + for(LNODEID ln1=lfirst(parts); ln1; ln1=lnext(ln1)) { + AVRPART *p = ldata(ln1); + int i; + for(i=0; i<3; i++) + if(p->signature[i] != sig[i]) + break; + if(i == 3) return p; } - } return NULL; } @@ -841,12 +740,11 @@ void walk_avrparts(LISTID avrparts, walk_avrparts_cb cb, void *cookie) /* * Compare function to sort the list of programmers */ -static int sort_avrparts_compare(AVRPART * p1,AVRPART * p2) -{ - if(p1 == NULL || p2 == NULL) { +static int sort_avrparts_compare(const AVRPART *p1, const AVRPART *p2) { + if(p1 == NULL || p1->desc == NULL || p2 == NULL || p2->desc == NULL) return 0; - } - return strncasecmp(p1->desc,p2->desc,AVR_DESCLEN); + + return strcasecmp(p1->desc, p2->desc); } /* @@ -868,9 +766,7 @@ static char * reset_disp_str(int r) } -void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose) -{ - int i; +void avr_display(FILE *f, const AVRPART *p, const char *prefix, int verbose) { char * buf; const char * px; LNODEID ln; @@ -905,23 +801,17 @@ void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose) fprintf( f, "%sMemory Detail :\n\n", prefix); px = prefix; - i = strlen(prefix) + 5; - buf = (char *)malloc(i); - if (buf == NULL) { - /* ugh, this is not important enough to bail, just ignore it */ - } - else { - strcpy(buf, prefix); - strcat(buf, " "); - px = buf; - } + buf = (char *)cfg_malloc("avr_display()", strlen(prefix) + 5); + strcpy(buf, prefix); + strcat(buf, " "); + px = buf; + + if (verbose <= 2) + avr_mem_display(px, f, NULL, p, verbose); - if (verbose <= 2) { - avr_mem_display(px, f, NULL, p, 0, verbose); - } for (ln=lfirst(p->mem); ln; ln=lnext(ln)) { m = ldata(ln); - avr_mem_display(px, f, m, p, i, verbose); + avr_mem_display(px, f, m, p, verbose); } if (buf) diff --git a/src/config.c b/src/config.c index f0b65822..ac712b17 100644 --- a/src/config.c +++ b/src/config.c @@ -83,13 +83,24 @@ int init_config(void) 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); + avrdude_message(MSG_INFO, "%s: out of memory in %s (needed %lu bytes)\n", progname, funcname, (unsigned long) n); exit(1); } memset(ret, 0, n); return ret; } +void *cfg_realloc(const char *funcname, void *p, size_t n) { + void *ret; + + if(!(ret = p? realloc(p, n): calloc(1, n))) { + avrdude_message(MSG_INFO, "%s: out of memory in %s (needed %lu bytes)\n", progname, funcname, (unsigned long) n); + exit(1); + } + + return ret; +} + char *cfg_strdup(const char *funcname, const char *s) { char *ret = strdup(s); @@ -323,35 +334,45 @@ int read_config(const char * file) } -// Linear-search cache for a few often-referenced strings -const char *cache_string(const char *file) { - static char **fnames; - static int n=0; +// Adapted version of a neat empirical hash function from comp.lang.c by Daniel Bernstein +unsigned strhash(const char *str) { + unsigned c, hash = 5381, n = 0; - if(!file) - return NULL; + while((c = (unsigned char) *str++) && n++ < 20) + hash = 33*hash ^ c; - // Exists in cache? - for(int i=0; iconfig_file = cache_string(cfg_infile); current_prog->lineno = cfg_lineno; } @@ -325,11 +321,6 @@ prog_decl : YYABORT; } current_prog = pgm_dup(pgm); - if (current_prog == NULL) { - yyerror("could not duplicate pgm instance"); - free_token($3); - YYABORT; - } current_prog->parent_id = cache_string($3->value.string); current_prog->config_file = cache_string(cfg_infile); current_prog->lineno = cfg_lineno; @@ -400,10 +391,6 @@ part_decl : K_PART { current_part = avr_new_part(); - if (current_part == NULL) { - yyerror("could not create part instance"); - YYABORT; - } current_part->config_file = cache_string(cfg_infile); current_part->lineno = cfg_lineno; } | @@ -417,11 +404,6 @@ part_decl : } current_part = avr_dup_part(parent_part); - if (current_part == NULL) { - yyerror("could not duplicate part instance"); - free_token($3); - YYABORT; - } current_part->parent_id = cache_string($3->value.string); current_part->config_file = cache_string(cfg_infile); current_part->lineno = cfg_lineno; @@ -465,8 +447,7 @@ prog_parm : prog_parm_conntype | K_DESC TKN_EQUAL TKN_STRING { - strncpy(current_prog->desc, $3->value.string, PGM_DESCLEN); - current_prog->desc[PGM_DESCLEN-1] = 0; + current_prog->desc = cache_string($3->value.string); free_token($3); } | K_BAUDRATE TKN_EQUAL TKN_NUMBER { @@ -686,22 +667,19 @@ retry_lines : part_parm : K_ID TKN_EQUAL TKN_STRING { - strncpy(current_part->id, $3->value.string, AVR_IDLEN); - current_part->id[AVR_IDLEN-1] = 0; + current_part->id = cache_string($3->value.string); free_token($3); } | K_DESC TKN_EQUAL TKN_STRING { - strncpy(current_part->desc, $3->value.string, AVR_DESCLEN - 1); - current_part->desc[AVR_DESCLEN-1] = 0; + current_part->desc = cache_string($3->value.string); free_token($3); } | K_FAMILY_ID TKN_EQUAL TKN_STRING { - strncpy(current_part->family_id, $3->value.string, AVR_FAMILYIDLEN); - current_part->family_id[AVR_FAMILYIDLEN] = 0; + current_part->family_id = cache_string($3->value.string); free_token($3); } | @@ -1289,13 +1267,8 @@ part_parm : { /* select memory for extension or create if not there */ AVRMEM *mem = avr_locate_mem_noalias(current_part, $2->value.string); if(!mem) { - if(!(mem = avr_new_memtype())) { - yyerror("could not create mem instance"); - free_token($2); - YYABORT; - } - strncpy(mem->desc, $2->value.string, AVR_MEMDESCLEN - 1); - mem->desc[AVR_MEMDESCLEN-1] = 0; + mem = avr_new_memtype(); + mem->desc = cache_string($2->value.string); ladd(current_part->mem, mem); } avr_add_mem_order($2->value.string); @@ -1339,11 +1312,6 @@ part_parm : opnum = which_opcode($1); if (opnum < 0) YYABORT; op = avr_new_opcode(); - if (op == NULL) { - yyerror("could not create opcode instance"); - free_token($1); - YYABORT; - } if(0 != parse_cmdbits(op, opnum)) YYABORT; if (current_part->op[opnum] != NULL) { @@ -1500,11 +1468,6 @@ mem_spec : opnum = which_opcode($1); if (opnum < 0) YYABORT; op = avr_new_opcode(); - if (op == NULL) { - yyerror("could not create opcode instance"); - free_token($1); - YYABORT; - } if(0 != parse_cmdbits(op, opnum)) YYABORT; if (current_mem->op[opnum] != NULL) { @@ -1553,10 +1516,7 @@ mem_alias : is_alias = true; alias = avr_new_memalias(); - - // alias->desc and current_mem->desc have the same length - // definition, thus no need to check for length here - strcpy(alias->desc, current_mem->desc); + alias->desc = current_mem->desc; alias->aliased_mem = existing_mem; ladd(current_part->mem_alias, alias); diff --git a/src/developer_opts.c b/src/developer_opts.c index 6cbfa4f2..f176563e 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -222,7 +222,7 @@ int dev_message(int msglvl, const char *fmt, ...) { -static int dev_part_strct_entry(bool tsv, char *col0, char *col1, char *col2, const char *name, char *cont) { +static int dev_part_strct_entry(bool tsv, const char *col0, const char *col1, const char *col2, const char *name, char *cont) { const char *n = name? name: "name_error"; const char *c = cont? cont: "cont_error"; @@ -286,23 +286,22 @@ static int intcmp(int a, int b) { // Deep copies for comparison and raw output typedef struct { + char descbuf[32]; AVRMEM base; OPCODE ops[AVR_OP_MAX]; } AVRMEMdeep; static int avrmem_deep_copy(AVRMEMdeep *d, AVRMEM *m) { - size_t len; - d->base = *m; - // Zap all bytes beyond terminating nul of desc array - len = strlen(m->desc)+1; - if(len < sizeof m->desc) - memset(d->base.desc + len, 0, sizeof m->desc - len); + // Note memory desc (name, really) is limited to 31 char here + memset(d->descbuf, 0, sizeof d->descbuf); + strncpy(d->descbuf, m->desc, sizeof d->descbuf-1); // Zap address values d->base.buf = NULL; d->base.tags = NULL; + d->base.desc = NULL; for(int i=0; ibase.op[i] = NULL; @@ -334,6 +333,9 @@ static int memorycmp(AVRMEM *m1, AVRMEM *m2) { typedef struct { + char descbuf[64]; + char idbuf[32]; + char family_idbuf[16]; AVRPART base; OPCODE ops[AVR_OP_MAX]; AVRMEMdeep mems[40]; @@ -341,7 +343,7 @@ typedef struct { static int avrpart_deep_copy(AVRPARTdeep *d, AVRPART *p) { AVRMEM *m; - size_t len, di; + size_t di; memset(d, 0, sizeof *d); @@ -351,20 +353,21 @@ static int avrpart_deep_copy(AVRPARTdeep *d, AVRPART *p) { d->base.config_file = NULL; d->base.lineno = 0; - // Zap all bytes beyond terminating nul of desc, id and family_id array - len = strlen(p->desc); - if(len < sizeof p->desc) - memset(d->base.desc + len, 0, sizeof p->desc - len); - - len = strlen(p->family_id); - if(len < sizeof p->family_id) - memset(d->base.family_id + len, 0, sizeof p->family_id - len); - - len = strlen(p->id); - if(len < sizeof p->id) - memset(d->base.id + len, 0, sizeof p->id - len); + // Copy over desc, id, and family_id + memset(d->descbuf, 0, sizeof d->descbuf); + if(d->descbuf) + strncpy(d->descbuf, p->desc, sizeof d->descbuf-1); + memset(d->idbuf, 0, sizeof d->idbuf); + if(d->idbuf) + strncpy(d->idbuf, p->id, sizeof d->idbuf-1); + memset(d->family_idbuf, 0, sizeof d->family_idbuf); + if(d->family_idbuf) + strncpy(d->family_idbuf, p->family_id, sizeof d->family_idbuf-1); // Zap address values + d->base.desc = NULL; + d->base.id = NULL; + d->base.family_id = NULL; d->base.mem = NULL; d->base.mem_alias = NULL; for(int i=0; i ' ' && in < 0x7f? in: '.'; + return in == 0? '.': in > ' ' && in < 0x7f? in: '_'; } static void dev_raw_dump(const char *p, int nbytes, const char *name, const char *sub, int idx) { int n = (nbytes + 31)/32; for(int i=0; idesc, "ops", 1); for(int i=0; idesc, dp.mems[i].base.desc, i+2); + dev_raw_dump((char *) (dp.mems+i), sizeof dp.mems[i], part->desc, dp.mems[i].descbuf, i+2); } @@ -680,7 +683,10 @@ void dev_output_part_defs(char *partdesc) { avr_add_mem_order(((AVRMEM_ALIAS *) ldata(lnm))->desc); } - nprinted = dev_nprinted; + if((nprinted = dev_nprinted)) { + dev_info("\n"); + nprinted = dev_nprinted; + } for(LNODEID ln1 = lfirst(part_list); ln1; ln1 = lnext(ln1)) { AVRPART *p = ldata(ln1); int flashsize, flashoffset, flashpagesize, eepromsize , eepromoffset, eeprompagesize; @@ -914,6 +920,8 @@ static void dev_pgm_raw(PROGRAMMER *pgm) { for(idx=0, ln=lfirst(dp.hvupdi_support); ln; ln=lnext(ln)) dev_raw_dump(ldata(ln), sizeof(int), id, "hvupdi_", idx++); + if(dp.desc) + dev_raw_dump(dp.desc, strlen(dp.desc)+1, id, "desc", 0); // Dump cache_string values if(dp.usbdev && *dp.usbdev) dev_raw_dump(dp.usbdev, strlen(dp.usbdev)+1, id, "usbdev", 0); @@ -925,14 +933,13 @@ static void dev_pgm_raw(PROGRAMMER *pgm) { dev_raw_dump(dp.usbproduct, strlen(dp.usbproduct)+1, id, "usbprod", 0); // Zap all bytes beyond terminating nul of desc, type and port array - if((len = strlen(dp.desc)+1) < sizeof dp.desc) - memset(dp.desc + len, 0, sizeof dp.desc - len); if((len = strlen(dp.type)+1) < sizeof dp.type) memset(dp.type + len, 0, sizeof dp.type - len); if((len = strlen(dp.port)+1) < sizeof dp.port) memset(dp.port + len, 0, sizeof dp.port - len); // Zap address values + dp.desc = NULL; dp.id = NULL; dp.parent_id = NULL; dp.initpgm = NULL; diff --git a/src/jtagmkI.c b/src/jtagmkI.c index e5d3d5d8..2e84eb5c 100644 --- a/src/jtagmkI.c +++ b/src/jtagmkI.c @@ -609,7 +609,7 @@ static int jtagmkI_initialize(PROGRAMMER * pgm, AVRPART * p) if (jtagmkI_reset(pgm) < 0) return -1; - strcpy(hfuse.desc, "hfuse"); + hfuse.desc = cache_string("hfuse"); if (jtagmkI_read_byte(pgm, p, &hfuse, 1, &b) < 0) return -1; if ((b & OCDEN) != 0) diff --git a/src/jtagmkII.c b/src/jtagmkII.c index 7181d186..f52f3bc3 100644 --- a/src/jtagmkII.c +++ b/src/jtagmkII.c @@ -1439,7 +1439,7 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p) } if ((pgm->flag & PGM_FL_IS_JTAG) && !(p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_UPDI))) { - strcpy(hfuse.desc, "hfuse"); + hfuse.desc = cache_string("hfuse"); if (jtagmkII_read_byte(pgm, p, &hfuse, 1, &b) < 0) return -1; if ((b & OCDEN) != 0) diff --git a/src/lexer.l b/src/lexer.l index 23fd2277..47c3cb25 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -45,8 +45,6 @@ DIGIT [0-9] HEXDIGIT [0-9a-fA-F] SIGN [+-] -%x incl -%x comment %option nounput /* Bump resources for classic lex. */ @@ -73,16 +71,12 @@ SIGN [+-] 0x{HEXDIGIT}+ { yylval = hexnumber(yytext); return TKN_NUMBER; } -# { /* The following captures all '#' style comments to end of line */ - BEGIN(comment); } -[^\n]*\n+ { /* eat comments */ - capture_comment_char('#'); +#[^\n]*\n+ { /* record and skip # comments */ + capture_comment_str(yytext); for(int i=0; yytext[i]; i++) { - capture_comment_char(yytext[i]); if(yytext[i] == '\n') cfg_lineno++; } - BEGIN(INITIAL); } diff --git a/src/libavrdude.h b/src/libavrdude.h index 3c2f2a57..cbbc8a79 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -203,8 +203,6 @@ typedef struct opcode { #define HV_UPDI_VARIANT_1 1 /* Dedicated UPDI pin, no HV (megaAVR0/AVR-Dx) */ #define HV_UPDI_VARIANT_2 2 /* Shared UPDI pin, HV on _RESET (AVR-Ex) */ -#define AVR_DESCLEN 64 -#define AVR_IDLEN 32 #define AVR_FAMILYIDLEN 7 #define AVR_SIBLEN 16 #define CTL_STACK_SIZE 32 @@ -215,10 +213,10 @@ typedef struct opcode { /* Any changes here, please also reflect in dev_part_strct() of developer_opts.c */ typedef struct avrpart { - char desc[AVR_DESCLEN]; /* long part name */ - char id[AVR_IDLEN]; /* short part name */ + const char * desc; /* long part name */ + const char * id; /* short part name */ const char * parent_id; /* parent id if set, for -p.../s */ - char family_id[AVR_FAMILYIDLEN+1]; /* family id in the SIB (avr8x) */ + const char * family_id; /* family id in the SIB (avr8x) */ int hvupdi_variant; /* HV pulse on UPDI pin, no pin or RESET pin */ int stk500_devcode; /* stk500 device code */ int avr910_devcode; /* avr910 device code */ @@ -286,7 +284,7 @@ typedef struct avrpart { #define AVR_MEMDESCLEN 64 typedef struct avrmem { - char desc[AVR_MEMDESCLEN]; /* memory description ("flash", "eeprom", etc) */ + const char *desc; /* memory description ("flash", "eeprom", etc) */ int paged; /* page addressed (e.g. ATmega flash) */ int size; /* total memory size in bytes */ int page_size; /* size of memory page (if page addressed) */ @@ -312,7 +310,7 @@ typedef struct avrmem { } AVRMEM; typedef struct avrmem_alias { - char desc[AVR_MEMDESCLEN]; /* alias name ("syscfg0" etc.) */ + const char *desc; /* alias name ("syscfg0" etc.) */ AVRMEM *aliased_mem; } AVRMEM_ALIAS; @@ -330,8 +328,8 @@ int avr_set_bits(OPCODE * op, unsigned char * cmd); int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr); int avr_set_addr_mem(AVRMEM *mem, int opnum, unsigned char *cmd, unsigned long addr); int avr_set_input(OPCODE * op, unsigned char * cmd, unsigned char data); -int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data); -int avr_get_output_index(OPCODE * op); +int avr_get_output(const OPCODE *op, const unsigned char *res, unsigned char *data); +int avr_get_output_index(const OPCODE *op); char cmdbitchar(CMDBIT cb); char *cmdbitstr(CMDBIT cb); const char *opcodename(int opnum); @@ -340,26 +338,26 @@ char *opcode2str(OPCODE *op, int opnum, int detailed); /* Functions for AVRMEM structures */ AVRMEM * avr_new_memtype(void); AVRMEM_ALIAS * avr_new_memalias(void); -int avr_initmem(AVRPART * p); -AVRMEM * avr_dup_mem(AVRMEM * m); +int avr_initmem(const AVRPART *p); +AVRMEM * avr_dup_mem(const AVRMEM *m); void avr_free_mem(AVRMEM * m); void avr_free_memalias(AVRMEM_ALIAS * m); -AVRMEM * avr_locate_mem(AVRPART * p, const char * desc); -AVRMEM * avr_locate_mem_noalias(AVRPART * p, const char * desc); -AVRMEM_ALIAS * avr_locate_memalias(AVRPART * p, const char * desc); -AVRMEM_ALIAS * avr_find_memalias(AVRPART * p, AVRMEM * m_orig); -void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p, - int type, int verbose); +AVRMEM * avr_locate_mem(const AVRPART *p, const char *desc); +AVRMEM * avr_locate_mem_noalias(const AVRPART *p, const char *desc); +AVRMEM_ALIAS * avr_locate_memalias(const AVRPART *p, const char *desc); +AVRMEM_ALIAS * avr_find_memalias(const AVRPART *p, const AVRMEM *m_orig); +void avr_mem_display(const char *prefix, FILE *f, const AVRMEM *m, + const AVRPART *p, int verbose); /* Functions for AVRPART structures */ AVRPART * avr_new_part(void); -AVRPART * avr_dup_part(AVRPART * d); +AVRPART * avr_dup_part(const AVRPART *d); void avr_free_part(AVRPART * d); -AVRPART * locate_part(LISTID parts, const char * partdesc); -AVRPART * locate_part_by_avr910_devcode(LISTID parts, int devcode); -AVRPART * locate_part_by_signature(LISTID parts, unsigned char * sig, +AVRPART * locate_part(const LISTID parts, const char *partdesc); +AVRPART * locate_part_by_avr910_devcode(const LISTID parts, int devcode); +AVRPART * locate_part_by_signature(const LISTID parts, unsigned char *sig, int sigsize); -void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose); +void avr_display(FILE *f, const AVRPART *p, const char *prefix, int verbose); typedef void (*walk_avrparts_cb)(const char *name, const char *desc, const char *cfgname, int cfglineno, @@ -653,7 +651,6 @@ extern struct serial_device usbhid_serdev; #define ON 1 #define OFF 0 -#define PGM_DESCLEN 80 #define PGM_PORTLEN PATH_MAX #define PGM_TYPELEN 32 @@ -685,7 +682,7 @@ typedef enum { /* Any changes here, please also reflect in dev_pgm_strct() of developer_opts.c */ typedef struct programmer_t { LISTID id; - char desc[PGM_DESCLEN]; + const char *desc; void (*initpgm)(struct programmer_t *pgm); const char *parent_id; // Used by developer options -c*/[sr...] struct pindef_t pin[N_PINS]; @@ -762,6 +759,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); + const char *config_file; // Config file where defined int lineno; // Config file line number void *cookie; // For private use by the programmer @@ -773,8 +771,8 @@ extern "C" { #endif PROGRAMMER * pgm_new(void); -PROGRAMMER * pgm_dup(const PROGRAMMER * const src); -void pgm_free(PROGRAMMER * const p); +PROGRAMMER * pgm_dup(const PROGRAMMER *src); +void pgm_free(PROGRAMMER *p); void programmer_display(PROGRAMMER * pgm, const char * p); @@ -783,10 +781,10 @@ void programmer_display(PROGRAMMER * pgm, const char * p); #define SHOW_PPI_PINS ((1<read_sib(pgm, p, sib); avrdude_message(MSG_NOTICE, "%s: System Information Block: \"%s\"\n", progname, sib); - if (quell_progress < 2) { + if (quell_progress < 2) avrdude_message(MSG_INFO, "%s: Received FamilyID: \"%.*s\"\n", progname, AVR_FAMILYIDLEN, sib); - } + if (strncmp(p->family_id, sib, AVR_FAMILYIDLEN)) { avrdude_message(MSG_INFO, "%s: Expected FamilyID: \"%s\"\n", progname, p->family_id); if (!ovsigck) { @@ -1093,9 +1093,8 @@ int main(int argc, char * argv []) avrdude_message(MSG_INFO, "%s: conflicting -e and -n options specified, NOT erasing chip\n", progname); } else { - if (quell_progress < 2) { + if (quell_progress < 2) avrdude_message(MSG_INFO, "%s: erasing chip\n", progname); - } exitrc = avr_unlock(pgm, p); if(exitrc) goto main_exit; goto sig_again; @@ -1229,9 +1228,8 @@ int main(int argc, char * argv []) avrdude_message(MSG_INFO, "%s: conflicting -e and -n options specified, NOT erasing chip\n", progname); } else { - if (quell_progress < 2) { + if (quell_progress < 2) avrdude_message(MSG_INFO, "%s: erasing chip\n", progname); - } exitrc = avr_chip_erase(pgm, p); if(exitrc) goto main_exit; } diff --git a/src/pgm.c b/src/pgm.c index 07cbed57..518b208e 100644 --- a/src/pgm.c +++ b/src/pgm.c @@ -61,31 +61,29 @@ static void pgm_default_powerup_powerdown (struct programmer_t * pgm) } -PROGRAMMER * pgm_new(void) -{ - int i; - PROGRAMMER * pgm; +PROGRAMMER *pgm_new(void) { + PROGRAMMER *pgm = (PROGRAMMER *) cfg_malloc("pgm_new()", sizeof(*pgm)); const char *nulp = cache_string(""); - pgm = (PROGRAMMER *) cfg_malloc("pgm_new()", sizeof(*pgm)); - + // Initialise const char * and LISTID entities pgm->id = lcreat(NULL, 0); pgm->usbpid = lcreat(NULL, 0); - pgm->desc[0] = 0; - pgm->type[0] = 0; - pgm->parent_id = nulp; - pgm->config_file = nulp; - pgm->lineno = 0; - pgm->baudrate = 0; - pgm->initpgm = NULL; pgm->hvupdi_support = lcreat(NULL, 0); - + pgm->desc = nulp; + pgm->parent_id = nulp; pgm->usbdev = nulp; pgm->usbsn = nulp; pgm->usbvendor = nulp; pgm->usbproduct = nulp; + pgm->config_file = nulp; - for (i=0; iinitpgm = NULL; + pgm->lineno = 0; + pgm->baudrate = 0; + + // Clear pin array + for(int i=0; ipinno[i] = 0; pin_clear_all(&(pgm->pin[i])); } @@ -121,49 +119,70 @@ PROGRAMMER * pgm_new(void) * optional functions - these are checked to make sure they are * assigned before they are called */ + pgm->unlock = NULL; pgm->cmd = NULL; pgm->cmd_tpi = NULL; pgm->spi = NULL; pgm->paged_write = NULL; pgm->paged_load = NULL; + pgm->page_erase = NULL; pgm->write_setup = NULL; pgm->read_sig_bytes = NULL; + pgm->read_sib = NULL; + pgm->print_parms = NULL; pgm->set_vtarget = NULL; pgm->set_varef = NULL; pgm->set_fosc = NULL; + pgm->set_sck_period = NULL; + pgm->setpin = NULL; + pgm->getpin = NULL; + pgm->highpulsepin = NULL; + pgm->parseexitspecs = NULL; pgm->perform_osccal = NULL; pgm->parseextparams = NULL; pgm->setup = NULL; pgm->teardown = NULL; + // For allocating "global" memory by the programmer + pgm->cookie = NULL; + return pgm; } -void pgm_free(PROGRAMMER * const p) -{ - ldestroy_cb(p->id, free); - ldestroy_cb(p->usbpid, free); - p->id = NULL; - p->usbpid = NULL; - /* do not free p->parent_id, p->config_file, p->usbdev, p->usbsn, p->usbvendor or p-> usbproduct */ - /* p->cookie is freed by pgm_teardown */ - free(p); +void pgm_free(PROGRAMMER *p) { + if(p) { + ldestroy_cb(p->id, free); + ldestroy_cb(p->usbpid, free); + ldestroy_cb(p->hvupdi_support, free); + p->id = NULL; + p->usbpid = NULL; + p->hvupdi_support = NULL; + // Never free const char *, eg, p->desc, which are set by cache_string() + // p->cookie is freed by pgm_teardown + free(p); + } } -PROGRAMMER * pgm_dup(const PROGRAMMER * const src) -{ - PROGRAMMER * pgm; - LNODEID ln; +PROGRAMMER *pgm_dup(const PROGRAMMER *src) { + PROGRAMMER *pgm = pgm_new(); - pgm = (PROGRAMMER *) cfg_malloc("pgm_dup()", sizeof(*pgm)); - memcpy(pgm, src, sizeof(*pgm)); + if(src) { + memcpy(pgm, src, sizeof(*pgm)); + pgm->id = lcreat(NULL, 0); + pgm->usbpid = lcreat(NULL, 0); + pgm->hvupdi_support = lcreat(NULL, 0); - pgm->id = lcreat(NULL, 0); - pgm->usbpid = lcreat(NULL, 0); - for (ln = lfirst(src->usbpid); ln; ln = lnext(ln)) { - int *ip = cfg_malloc("pgm_dup()", sizeof(int)); - *ip = *(int *) ldata(ln); - ladd(pgm->usbpid, ip); + // Leave id list empty but copy usbpid and hvupdi_support over + for(LNODEID ln = lfirst(src->hvupdi_support); ln; ln = lnext(ln)) { + int *ip = cfg_malloc("pgm_dup()", sizeof(int)); + *ip = *(int *) ldata(ln); + ladd(pgm->hvupdi_support, ip); + } + for(LNODEID ln = lfirst(src->usbpid); ln; ln = lnext(ln)) { + int *ip = cfg_malloc("pgm_dup()", sizeof(int)); + *ip = *(int *) ldata(ln); + ladd(pgm->usbpid, ip); + } } return pgm; @@ -207,8 +226,7 @@ static void pgm_default_6 (struct programmer_t * pgm, const char * p) } -void programmer_display(PROGRAMMER * pgm, const char * p) -{ +void programmer_display(PROGRAMMER *pgm, const char * p) { avrdude_message(MSG_INFO, "%sProgrammer Type : %s\n", p, pgm->type); avrdude_message(MSG_INFO, "%sDescription : %s\n", p, pgm->desc); @@ -216,8 +234,7 @@ void programmer_display(PROGRAMMER * pgm, const char * p) } -void pgm_display_generic_mask(PROGRAMMER * pgm, const char * p, unsigned int show) -{ +void pgm_display_generic_mask(const PROGRAMMER *pgm, const char *p, unsigned int show) { if(show & (1<pin[PPI_AVR_VCC])); if(show & (1<pin[PIN_LED_VFY])); } -void pgm_display_generic(PROGRAMMER * pgm, const char * p) -{ +void pgm_display_generic(const PROGRAMMER *pgm, const char *p) { pgm_display_generic_mask(pgm, p, SHOW_ALL_PINS); } -PROGRAMMER * locate_programmer(LISTID programmers, const char * configid) -{ - LNODEID ln1, ln2; - PROGRAMMER * p = NULL; - const char * id; - int found; +PROGRAMMER *locate_programmer(const LISTID programmers, const char *configid) { + PROGRAMMER *p = NULL; + int found = 0; - found = 0; - - for (ln1=lfirst(programmers); ln1 && !found; ln1=lnext(ln1)) { + for(LNODEID ln1=lfirst(programmers); ln1 && !found; ln1=lnext(ln1)) { p = ldata(ln1); - for (ln2=lfirst(p->id); ln2 && !found; ln2=lnext(ln2)) { - id = ldata(ln2); - if (strcasecmp(configid, id) == 0) + for(LNODEID ln2=lfirst(p->id); ln2 && !found; ln2=lnext(ln2)) + if(strcasecmp(configid, (const char *) ldata(ln2)) == 0) found = 1; - } } - if (found) - return p; - - return NULL; + return found? p: NULL; } /* @@ -296,16 +302,11 @@ void walk_programmers(LISTID programmers, walk_programmers_cb cb, void *cookie) /* * Compare function to sort the list of programmers */ -static int sort_programmer_compare(PROGRAMMER * p1,PROGRAMMER * p2) -{ - char* id1; - char* id2; - if(p1 == NULL || p2 == NULL) { +static int sort_programmer_compare(const PROGRAMMER *p1, const PROGRAMMER *p2) { + if(p1 == NULL || p1->id == NULL || p2 == NULL || p2->id == NULL) return 0; - } - id1 = ldata(lfirst(p1->id)); - id2 = ldata(lfirst(p2->id)); - return strncasecmp(id1,id2,AVR_IDLEN); + + return strcasecmp(ldata(lfirst(p1->id)), ldata(lfirst(p2->id))); } /* diff --git a/src/pickit2.c b/src/pickit2.c index ac3781f5..a1d32f88 100644 --- a/src/pickit2.c +++ b/src/pickit2.c @@ -193,16 +193,18 @@ static int pickit2_open(PROGRAMMER * pgm, char * port) } else { - // get the device description while we're at it - short buff[PGM_DESCLEN-1], i; - HidD_GetProductString(PDATA(pgm)->usb_handle, buff, PGM_DESCLEN-1); + // Get the device description while we're at it and overlay it on pgm->desc + short wbuf[80-1]; + char *cbuf = cfg_malloc("pickit2_open()", sizeof wbuf/sizeof*wbuf + (pgm->desc? strlen(pgm->desc): 0) + 2); + HidD_GetProductString(PDATA(pgm)->usb_handle, wbuf, sizeof wbuf/sizeof*wbuf); - // convert from wide chars, but do not overwrite trailing '\0' - memset(&(pgm->desc), 0, PGM_DESCLEN); - for (i = 0; i < (PGM_DESCLEN-1) && buff[i]; i++) - { - pgm->desc[i] = (char)buff[i]; // TODO what about little/big endian??? - } + if(pgm->desc && *pgm->desc) + strcpy(cbuf, pgm->desc); + + // Convert from wide chars and overlay over initial part of desc + for (int i = 0; i < sizeof wbuf/sizeof*wbuf && wbuf[i]; i++) + cbuf[i] = (char) wbuf[i]; // TODO what about little/big endian??? + pgm->desc = cache_string(cbuf); } #else if (usb_open_device(&(PDATA(pgm)->usb_handle), PICKIT2_VID, PICKIT2_PID) < 0) diff --git a/src/update.c b/src/update.c index 972c3847..f3dbd335 100644 --- a/src/update.c +++ b/src/update.c @@ -306,11 +306,11 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f return LIBAVRDUDE_SOFTFAIL; } - AVRMEM_ALIAS * alias_mem = avr_find_memalias(p, mem); - char alias_mem_desc[AVR_DESCLEN + 1] = ""; - if(alias_mem) { - strcat(alias_mem_desc, "/"); - strcat(alias_mem_desc, alias_mem->desc); + AVRMEM_ALIAS *alias_mem = avr_find_memalias(p, mem); + char *alias_mem_desc = cfg_malloc("do_op()", 2 + (alias_mem && alias_mem->desc? strlen(alias_mem->desc): 0)); + if(alias_mem && alias_mem->desc && *alias_mem->desc) { + *alias_mem_desc = '/'; + strcpy(alias_mem_desc+1, alias_mem->desc); } switch (upd->op) { From c9cf308037a16d97f2be43d655af0d4c1da0ec5c Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Wed, 10 Aug 2022 16:24:26 +0100 Subject: [PATCH 13/19] Include ctype.h in term.c to resolve missing functions --- src/term.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/term.c b/src/term.c index 672a09cd..839e5608 100644 --- a/src/term.c +++ b/src/term.c @@ -20,6 +20,7 @@ #include "ac_cfg.h" +#include #include #include #include From ccb576ebc1af85a3dee6dd005aebb4e68e54b7cf Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Wed, 10 Aug 2022 22:25:19 +0100 Subject: [PATCH 14/19] Ensure memories are printed at most once for -p */S --- src/developer_opts.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/developer_opts.c b/src/developer_opts.c index f176563e..32d2c71e 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -383,7 +383,7 @@ static int avrpart_deep_copy(AVRPARTdeep *d, AVRPART *p) { // Fill in all memories we got in defined order di = 0; for(size_t mi=0; mi < sizeof avr_mem_order/sizeof *avr_mem_order && avr_mem_order[mi]; mi++) { - m = p->mem? avr_locate_mem(p, avr_mem_order[mi]): NULL; + m = p->mem? avr_locate_mem_noalias(p, avr_mem_order[mi]): NULL; if(m) { if(di >= sizeof d->mems/sizeof *d->mems) { avrdude_message(MSG_INFO, "%s: ran out of mems[] space, increase size in AVRMEMdeep of developer_opts.c and recompile\n", progname); @@ -553,8 +553,8 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) { for(size_t mi=0; mi < sizeof avr_mem_order/sizeof *avr_mem_order && avr_mem_order[mi]; mi++) { AVRMEM *m, *bm; - m = p->mem? avr_locate_mem(p, avr_mem_order[mi]): NULL; - bm = base && base->mem? avr_locate_mem(base, avr_mem_order[mi]): NULL; + m = p->mem? avr_locate_mem_noalias(p, avr_mem_order[mi]): NULL; + bm = base && base->mem? avr_locate_mem_noalias(base, avr_mem_order[mi]): NULL; if(!m && bm && !tsv) dev_info("\n memory \"%s\" = NULL;\n", bm->desc); From c2c9053b1388bfbb03c947e05be63bfe036c26bc Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Fri, 12 Aug 2022 00:28:54 +0100 Subject: [PATCH 15/19] Show comments with -p*/s or -c*/s and reduce -p */r raw output --- src/config.c | 100 +++++++++++++- src/config.h | 21 ++- src/config_gram.y | 41 +++--- src/developer_opts.c | 239 ++++++++++++++++++++++++++------- src/developer_opts.h | 1 + src/developer_opts_private.h | 49 +++---- src/lexer.l | 252 ++++++++++++++++++----------------- src/libavrdude.h | 7 +- src/main.c | 26 ++-- 9 files changed, 505 insertions(+), 231 deletions(-) diff --git a/src/config.c b/src/config.c index ac712b17..d36e0814 100644 --- a/src/config.c +++ b/src/config.c @@ -371,10 +371,98 @@ const char *cache_string(const char *p) { return hstrings[h][k] = cfg_strdup("cache_string()", p); } -// Captures comments during parsing -void capture_comment_str(const char *p) { + +static LISTID cfg_comms; // A chain of comment lines +static LISTID cfg_prologue; // Comment lines at start of avrdude.conf +static char *lkw; // Last seen keyword +static int lkw_lineno; // Line number of that + +static LISTID cfg_strctcomms; // Passed on to config_gram.y +static LISTID cfg_pushedcomms; // Temporarily pushed main comments +static int cfg_pushed; // ... for memory sections + +COMMENT *locate_comment(const LISTID comments, const char *where, int rhs) { + if(comments) + for(LNODEID ln=lfirst(comments); ln; ln=lnext(ln)) { + COMMENT *n = ldata(ln); + if(n && rhs == n->rhs && n->kw && strcmp(where, n->kw) == 0) + return n; + } + + return NULL; } +static void addcomment(int rhs) { + if(lkw) { + COMMENT *node = cfg_malloc("addcomment()", sizeof(*node)); + node->rhs = rhs; + node->kw = cfg_strdup("addcomment()", lkw); + node->comms = cfg_comms; + cfg_comms = NULL; + if(!cfg_strctcomms) + cfg_strctcomms = lcreat(NULL, 0); + ladd(cfg_strctcomms, node); + } +} + +// Capture prologue during parsing (triggered by lexer.l) +void cfg_capture_prologue(void) { + cfg_prologue = cfg_comms; + cfg_comms = NULL; +} + +LISTID cfg_get_prologue(void) { + return cfg_prologue; +} + +// Captures comments during parsing +void capture_comment_str(const char *com, int lineno) { + if(!cfg_comms) + cfg_comms = lcreat(NULL, 0); + ladd(cfg_comms, cfg_strdup("capture_comment_str()", com)); + + // Last keyword lineno is the same as this comment's + if(lkw && lkw_lineno == lineno) + addcomment(1); // Register comms to show right of lkw = ...; +} + +// Capture assignments (keywords left of =) and associate comments to them +void capture_lvalue_kw(const char *kw, int lineno) { + if(!strcmp(kw, "memory")) { // Push part comments and start memory comments + if(!cfg_pushed) { // config_gram.y pops the part comments + cfg_pushed = 1; + cfg_pushedcomms = cfg_strctcomms; + cfg_strctcomms = NULL; + } + } + + if(!strcmp(kw, "programmer") || !strcmp(kw, "part") || !strcmp(kw, "memory")) + kw = "*"; // Show comment before programmer/part/memory + + if(lkw) + free(lkw); + lkw = cfg_strdup("capture_lvalue_kw()", kw); + lkw_lineno = lineno; + if(cfg_comms) // Accrued list of # one-line comments + addcomment(0); // Register comment to appear before lkw assignment +} + +// config_gram.y calls this once for each programmer/part/memory structure +LISTID cfg_move_comments(void) { + capture_lvalue_kw(";", -1); + + LISTID ret = cfg_strctcomms; + cfg_strctcomms = NULL; + return ret; +} + +// config_gram.y calls this after ingressing the memory structure +void cfg_pop_comms(void) { + if(cfg_pushed) { + cfg_pushed = 0; + cfg_strctcomms = cfg_pushedcomms; + } +} // Convert the next n hex digits of s to a hex number static unsigned int tohex(const unsigned char *s, unsigned int n) { @@ -558,12 +646,12 @@ 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 +// Return an escaped string that looks like a C-style input string incl quotes, memory is malloc'd char *cfg_escape(const char *s) { - char *ret = (char *) cfg_malloc("cfg_escape()", 4*strlen(s)+2+3), *d = ret; + char buf[50*1024], *d = buf; *d++ = '"'; - for(; *s; s++) { + for(; *s && d-buf < sizeof buf-7; s++) { switch(*s) { case '\n': *d++ = '\\'; *d++ = 'n'; @@ -602,5 +690,5 @@ char *cfg_escape(const char *s) { *d++ = '"'; *d = 0; - return ret; + return cfg_strdup("cfg_escape()", buf); } diff --git a/src/config.h b/src/config.h index afd39b17..b8bd2031 100644 --- a/src/config.h +++ b/src/config.h @@ -30,6 +30,13 @@ #endif +typedef struct { + char *kw; // Keyword near the comments + LISTID comms; // Chained list of comments + int rhs; // Comments to print rhs of keyword line +} COMMENT; + + enum { V_NONE, V_NUM, V_NUM_REAL, V_STR }; typedef struct value_t { int type; @@ -94,7 +101,19 @@ void print_token(TOKEN *tkn); void pyytext(void); -void capture_comment_str(const char *str); +COMMENT *locate_comment(const LISTID comments, const char *where, int rhs); + +void cfg_capture_prologue(void); + +LISTID cfg_get_prologue(void); + +void capture_comment_str(const char *com, int lineno); + +void capture_lvalue_kw(const char *kw, int lineno); + +LISTID cfg_move_comments(void); + +void cfg_pop_comms(void); #ifdef __cplusplus } diff --git a/src/config_gram.y b/src/config_gram.y index 2a027c7f..2c3504f2 100644 --- a/src/config_gram.y +++ b/src/config_gram.y @@ -297,6 +297,7 @@ prog_def : lrmv_d(programmers, existing_prog); pgm_free(existing_prog); } + current_prog->comments = cfg_move_comments(); LISTADD(programmers, current_prog); // pgm_fill_old_pins(current_prog); // TODO to be removed if old pin data no longer needed // pgm_display_generic(current_prog, id); @@ -322,6 +323,7 @@ prog_decl : } current_prog = pgm_dup(pgm); current_prog->parent_id = cache_string($3->value.string); + current_prog->comments = NULL; current_prog->config_file = cache_string(cfg_infile); current_prog->lineno = cfg_lineno; free_token($3); @@ -341,32 +343,33 @@ part_def : YYABORT; } - /* - * perform some sanity checking, and compute the number of bits - * to shift a page for constructing the page address for - * page-addressed memories. - */ + // Sanity checks for memory sizes and compute/override num_pages entry for (ln=lfirst(current_part->mem); ln; ln=lnext(ln)) { m = ldata(ln); if (m->paged) { - if (m->page_size == 0) { - yyerror("must specify page_size for paged memory"); + if (m->size <= 0) { + yyerror("must specify a positive size for paged memory %s", m->desc); YYABORT; } - if (m->num_pages == 0) { - yyerror("must specify num_pages for paged memory"); + if (m->page_size <= 0) { + yyerror("must specify a positive page size for paged memory %s", m->desc); YYABORT; } - if (m->size != m->page_size * m->num_pages) { - yyerror("page size (%u) * num_pages (%u) = " - "%u does not match memory size (%u)", - m->page_size, - m->num_pages, - m->page_size * m->num_pages, - m->size); + // Code base relies on page_size being a power of 2 in some places + if (m->page_size & (m->page_size - 1)) { + yyerror("page size must be a power of 2 for paged memory %s", m->desc); YYABORT; } + // Code base relies on size being a multiple of page_size + if (m->size % m->page_size) { + yyerror("size must be a multiple of page size for paged memory %s", m->desc); + YYABORT; + } + // Warn if num_pages was specified but is inconsistent with size and page size + if (m->num_pages && m->num_pages != m->size / m->page_size) + yywarning("overriding num_page to be %d for memory %s", m->size/m->page_size, m->desc); + m->num_pages = m->size / m->page_size; } } @@ -382,6 +385,8 @@ part_def : lrmv_d(part_list, existing_part); avr_free_part(existing_part); } + + current_part->comments = cfg_move_comments(); LISTADD(part_list, current_part); current_part = NULL; } @@ -405,6 +410,7 @@ part_decl : current_part = avr_dup_part(parent_part); current_part->parent_id = cache_string($3->value.string); + current_part->comments = NULL; current_part->config_file = cache_string(cfg_infile); current_part->lineno = cfg_lineno; @@ -1291,7 +1297,9 @@ part_parm : yywarning("%s's %s %s misses a necessary address bit a%d", current_part->desc, current_mem->desc, opcodename(i), bn-1); } + current_mem->comments = cfg_move_comments(); } + cfg_pop_comms(); current_mem = NULL; } | K_MEMORY TKN_STRING TKN_EQUAL K_NULL @@ -1302,6 +1310,7 @@ part_parm : avr_free_mem(existing_mem); } free_token($2); + cfg_pop_comms(); current_mem = NULL; } | opcode TKN_EQUAL string_list { diff --git a/src/developer_opts.c b/src/developer_opts.c index 32d2c71e..e0c274b9 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -48,6 +48,7 @@ #include "avrdude.h" #include "libavrdude.h" +#include "config.h" #include "developer_opts.h" #include "developer_opts_private.h" @@ -221,8 +222,49 @@ int dev_message(int msglvl, const char *fmt, ...) { } +// Any of the strings in the list contains subs as substring? +int dev_has_subsstr_comms(const LISTID comms, const char *subs) { + if(comms) + for(LNODEID ln=lfirst(comms); ln; ln=lnext(ln)) + if(strstr((char *) ldata(ln), subs)) + return 1; + return 0; +} + +// Print a chained list of strings +void dev_print_comment(const LISTID comms) { + if(comms) + for(LNODEID ln=lfirst(comms); ln; ln=lnext(ln)) + dev_info("%s", (char *) ldata(ln)); +} + +// Conditional output of part, memory or programmer's comments field +static void dev_cout(const LISTID comms, const char *name, int rhs, int elself) { + COMMENT *cp; + + if((cp = locate_comment(comms, name, rhs))) + dev_print_comment(cp->comms); + else if(elself) + dev_info("\n"); +} + +// Print part->comments, mem->comments or pgm->comments (for debugging) +void dev_print_kw_comments(const LISTID comms) { + if(comms) + for(LNODEID ln=lfirst(comms); ln; ln=lnext(ln)) { + COMMENT *n = ldata(ln); + if(n && n->comms) { + dev_info(">>> %s %c\n", n->kw, n->rhs? '>': '<'); + dev_print_comment(n->comms); + } + } +} + +// Ideally all assignment outputs run via this function +static int dev_part_strct_entry(bool tsv, // Print as spreadsheet? + const char *col0, const char *col1, const char *col2, // Descriptors of item + const char *name, char *cont, const LISTID comms) { // Name, contents and comments -static int dev_part_strct_entry(bool tsv, const char *col0, const char *col1, const char *col2, const char *name, char *cont) { const char *n = name? name: "name_error"; const char *c = cont? cont: "cont_error"; @@ -239,8 +281,9 @@ static int dev_part_strct_entry(bool tsv, const char *col0, const char *col1, co dev_info("%s\t%s\n", n, c); } else { // Grammar conform int indent = col2 && strcmp(col2, "part"); - - printf("%*s%-*s = %s;\n", indent? 8: 4, "", indent? 15: 19, n, c); + dev_cout(comms, n, 0, 0); // Print comments before the line + dev_info("%*s%-*s = %s;", indent? 8: 4, "", indent? 15: 19, n, c); + dev_cout(comms, n, 1, 1); // Print comments on rhs } if(cont) @@ -267,14 +310,18 @@ static void dev_stack_out(bool tsv, AVRPART *p, const char *name, unsigned char if(tsv) dev_info(".pt\t%s\t%s\t", p->desc, name); - else + else { + dev_cout(p->comments, name, 0, 0); dev_info(" %-19s =%s", name, ns <=8? " ": ""); + } if(ns <= 0) - dev_info(tsv? "NULL\n": "NULL;\n"); + dev_info(tsv? "NULL\n": "NULL;"); else for(int i=0; i 8 && i%8 == 0? "\n ": "", stack[i], i+1 8 && i%8 == 0? "\n ": "", stack[i], i+1comments, name, 1, 1); } @@ -291,7 +338,7 @@ typedef struct { OPCODE ops[AVR_OP_MAX]; } AVRMEMdeep; -static int avrmem_deep_copy(AVRMEMdeep *d, AVRMEM *m) { +static int avrmem_deep_copy(AVRMEMdeep *d, const AVRMEM *m) { d->base = *m; // Note memory desc (name, really) is limited to 31 char here @@ -299,17 +346,16 @@ static int avrmem_deep_copy(AVRMEMdeep *d, AVRMEM *m) { strncpy(d->descbuf, m->desc, sizeof d->descbuf-1); // Zap address values + d->base.comments = NULL; d->base.buf = NULL; d->base.tags = NULL; d->base.desc = NULL; for(int i=0; ibase.op[i] = NULL; - // Copy over the SPI operations themselves - memset(d->base.op, 0, sizeof d->base.op); memset(d->ops, 0, sizeof d->ops); - for(size_t i=0; iops/sizeof *d->ops; i++) + for(size_t i=0; iop[i]) d->ops[i] = *m->op[i]; @@ -324,7 +370,7 @@ static int memorycmp(AVRMEM *m1, AVRMEM *m2) { if(!m1 || !m2) return m1? -1: 1; - + avrmem_deep_copy(&dm1, m1); avrmem_deep_copy(&dm2, m2); @@ -341,7 +387,7 @@ typedef struct { AVRMEMdeep mems[40]; } AVRPARTdeep; -static int avrpart_deep_copy(AVRPARTdeep *d, AVRPART *p) { +static int avrpart_deep_copy(AVRPARTdeep *d, const AVRPART *p) { AVRMEM *m; size_t di; @@ -349,6 +395,7 @@ static int avrpart_deep_copy(AVRPARTdeep *d, AVRPART *p) { d->base = *p; + d->base.comments = NULL; d->base.parent_id = NULL; d->base.config_file = NULL; d->base.lineno = 0; @@ -373,8 +420,7 @@ static int avrpart_deep_copy(AVRPARTdeep *d, AVRPART *p) { for(int i=0; ibase.op[i] = NULL; - // Copy over the SPI operations - memset(d->base.op, 0, sizeof d->base.op); + // Copy over all used SPI operations memset(d->ops, 0, sizeof d->ops); for(int i=0; iop[i]) @@ -403,7 +449,8 @@ static char txtchar(unsigned char in) { return in == 0? '.': in > ' ' && in < 0x7f? in: '_'; } -static void dev_raw_dump(const char *p, int nbytes, const char *name, const char *sub, int idx) { +static void dev_raw_dump(const void *v, int nbytes, const char *name, const char *sub, int idx) { + const unsigned char *p = v; int n = (nbytes + 31)/32; for(int i=0; idesc, "part", 0); - dev_raw_dump((char *) &dp.ops, sizeof dp.ops, part->desc, "ops", 1); + dev_raw_dump(&dp.base, sizeof dp.base, part->desc, "part", 0); + for(int i=0; idesc, opsnm("part", i), 1); - for(int i=0; idesc, dp.mems[i].descbuf, i+2); + for(int i=0; idesc, nm, i+2); + dev_raw_dump(&dp.mems[i].base, sizeof dp.mems[i].base, part->desc, nm, i+2); + for(int j=0; jdesc, opsnm(nm, j), i+2); + } } static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) { - char *descstr = cfg_escape(p->desc); + COMMENT *cp; + if(!tsv) { - dev_info("#------------------------------------------------------------\n"); - dev_info("# %.*s\n", strlen(descstr+1)-1, descstr+1); - dev_info("#------------------------------------------------------------\n"); + const char *del = "#------------------------------------------------------------"; + cp = locate_comment(p->comments, "*", 0); + + if(!cp || !dev_has_subsstr_comms(cp->comms, del)) { + dev_info("%s\n", del); + dev_info("# %.*s\n", strlen(descstr)-2, descstr+1); // Remove double quotes + dev_info("%s\n\n", del); + } + if(cp) + dev_print_comment(cp->comms); + if(p->parent_id && *p->parent_id) - dev_info("\npart parent \"%s\"\n", p->parent_id); + dev_info("part parent \"%s\"\n", p->parent_id); else - dev_info("\npart\n"); + dev_info("part\n"); } _if_partout_str(strcmp, descstr, desc); @@ -548,7 +623,7 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) { for(int i=0; i < AVR_OP_MAX; i++) if(!base || opcodecmp(p->op[i], base->op[i], i)) - dev_part_strct_entry(tsv, ".ptop", p->desc, "part", opcodename(i), opcode2str(p->op[i], i, !tsv)); + dev_part_strct_entry(tsv, ".ptop", p->desc, "part", opcodename(i), opcode2str(p->op[i], i, !tsv), p->comments); for(size_t mi=0; mi < sizeof avr_mem_order/sizeof *avr_mem_order && avr_mem_order[mi]; mi++) { AVRMEM *m, *bm; @@ -569,7 +644,8 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) { if(!memorycmp(bm, m)) // Same memory bit for bit, no need to instantiate continue; - dev_info("\n memory \"%s\"\n", m->desc); + dev_cout(m->comments, "*", 0, 1); + dev_info(" memory \"%s\"\n", m->desc); } _if_memout_yn(paged); @@ -589,10 +665,12 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) { for(int i=0; i < AVR_OP_MAX; i++) if(!bm || opcodecmp(bm->op[i], m->op[i], i)) - dev_part_strct_entry(tsv, ".ptmmop", p->desc, m->desc, opcodename(i), opcode2str(m->op[i], i, !tsv)); + dev_part_strct_entry(tsv, ".ptmmop", p->desc, m->desc, opcodename(i), opcode2str(m->op[i], i, !tsv), m->comments); - if(!tsv) + if(!tsv) { + dev_cout(m->comments, ";", 0, 0); dev_info(" ;\n"); + } for(LNODEID lnm=lfirst(p->mem_alias); lnm; lnm=lnext(lnm)) { AVRMEM_ALIAS *ma = ldata(lnm); @@ -605,8 +683,37 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) { } } - if(!tsv) + if(!tsv) { + dev_cout(p->comments, ";", 0, 0); dev_info(";\n"); + } +} + + +void dev_output_pgm_part(int dev_opt_c, char *programmer, int dev_opt_p, char *partdesc) { + if(dev_opt_c == 2 && dev_opt_p == 2) { + char *p; + + dev_print_comment(cfg_get_prologue()); + + dev_info("default_programmer = %s;\n", p = cfg_escape(default_programmer)); free(p); + dev_info("default_parallel = %s;\n", p = cfg_escape(default_parallel)); free(p); + dev_info("default_serial = %s;\n", p = cfg_escape(default_serial)); free(p); + dev_info("default_spi = %s;\n", p = cfg_escape(default_spi)); free(p); + + dev_info("\n#\n# PROGRAMMER DEFINITIONS\n#\n\n"); + } + + if(dev_opt_c) + dev_output_pgm_defs(cfg_strdup("main()", programmer)); + + if(dev_opt_p == 2 && dev_opt_c) + dev_info("\n"); + if(dev_opt_p == 2) + dev_info("#\n# PART DEFINITIONS\n#\n"); + + if(dev_opt_p) + dev_output_part_defs(cfg_strdup("main()", partdesc)); } @@ -941,6 +1048,7 @@ static void dev_pgm_raw(PROGRAMMER *pgm) { // Zap address values dp.desc = NULL; dp.id = NULL; + dp.comments = NULL; dp.parent_id = NULL; dp.initpgm = NULL; dp.usbpid = NULL; @@ -968,29 +1076,38 @@ static const char *connstr(conntype_t conntype) { static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) { char *id = ldata(lfirst(pgm->id)); LNODEID ln; + COMMENT *cp; int firstid; if(!tsv) { - dev_info("#------------------------------------------------------------\n"); - dev_info("# "); - for(firstid=1, ln=lfirst(pgm->id); ln; ln=lnext(ln)) { - if(!firstid) - dev_info("/"); - firstid = 0; - dev_info("%s", ldata(ln)); + const char *del = "#------------------------------------------------------------"; + cp = locate_comment(pgm->comments, "*", 0); + + if(!cp || !dev_has_subsstr_comms(cp->comms, del)) { + dev_info("%s\n# ", del); + for(firstid=1, ln=lfirst(pgm->id); ln; ln=lnext(ln)) { + if(!firstid) + dev_info("/"); + firstid = 0; + dev_info("%s", ldata(ln)); + } + dev_info("\n%s\n\n", del); } - dev_info("\n"); - dev_info("#------------------------------------------------------------\n"); + if(cp) + dev_print_comment(cp->comms); + if(pgm->parent_id && *pgm->parent_id) - dev_info("\nprogrammer parent \"%s\"\n", pgm->parent_id); + dev_info("programmer parent \"%s\"\n", pgm->parent_id); else - dev_info("\nprogrammer\n"); + dev_info("programmer\n"); } if(tsv) dev_info(".prog\t%s\tid\t", id); - else + else { + dev_cout(pgm->comments, "id", 0, 0); dev_info(" %-19s = ", "id"); + } for(firstid=1, ln=lfirst(pgm->id); ln; ln=lnext(ln)) { if(!firstid) dev_info(", "); @@ -999,7 +1116,12 @@ static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) { dev_info("%s", str); free(str); } - dev_info(tsv? "\n": ";\n"); + if(tsv) + dev_info("\n"); + else { + dev_info(";"); + dev_cout(pgm->comments, "id", 1, 1); + } _if_pgmout_str(strcmp, cfg_escape(pgm->desc), desc); _pgmout_fmt("type", "\"%s\"", locate_programmer_type_id(pgm->initpgm)); @@ -1012,15 +1134,22 @@ static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) { if(pgm->usbpid && lfirst(pgm->usbpid)) { if(tsv) dev_info(".prog\t%s\tusbpid\t", id); - else + else { + dev_cout(pgm->comments, "usbpid", 0, 0); dev_info(" %-19s = ", "usbpid"); + } for(firstid=1, ln=lfirst(pgm->usbpid); ln; ln=lnext(ln)) { if(!firstid) dev_info(", "); firstid = 0; dev_info("0x%04x", *(unsigned int *) ldata(ln)); } - dev_info(tsv? "\n": ";\n"); + if(tsv) + dev_info("\n"); + else { + dev_info(";"); + dev_cout(pgm->comments, "usbpid", 1, 1); + } } _if_pgmout_str(strcmp, cfg_escape(pgm->usbdev), usbdev); @@ -1039,20 +1168,28 @@ static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) { if(pgm->hvupdi_support && lfirst(pgm->hvupdi_support)) { if(tsv) dev_info(".prog\t%s\thvupdu_support\t", id); - else + else { + dev_cout(pgm->comments, "hvupdi_support", 0, 0); dev_info(" %-19s = ", "hvupdi_support"); + } for(firstid=1, ln=lfirst(pgm->hvupdi_support); ln; ln=lnext(ln)) { if(!firstid) dev_info(", "); firstid = 0; dev_info("%d", *(unsigned int *) ldata(ln)); } - dev_info(tsv? "\n": ";\n"); + if(tsv) + dev_info("\n"); + else { + dev_info(";"); + dev_cout(pgm->comments, "hvupdi_support", 1, 1); + } } - - if(!tsv) + if(!tsv) { + dev_cout(pgm->comments, ";", 0, 0); dev_info(";\n"); + } } diff --git a/src/developer_opts.h b/src/developer_opts.h index 2079c109..bc04a9d8 100644 --- a/src/developer_opts.h +++ b/src/developer_opts.h @@ -19,6 +19,7 @@ #ifndef developer_opts_h #define developer_opts_h +void dev_output_pgm_part(int dev_opt_c, char *programmer, int dev_opt_p, char *partdesc); void dev_output_part_defs(char *partdesc); void dev_output_pgm_defs(char *programmer); diff --git a/src/developer_opts_private.h b/src/developer_opts_private.h index a5c1562e..54012838 100644 --- a/src/developer_opts_private.h +++ b/src/developer_opts_private.h @@ -52,76 +52,77 @@ static int dev_message(int msglvl, const char *fmt, ...); #define dev_notice2(...) dev_message(DEV_NOTICE2, __VA_ARGS__) #define _pgmout(fmt, component) \ - 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), pgm->comments) #define _pgmout_fmt(name, fmt, what) \ - dev_part_strct_entry(tsv, ".prog", id, NULL, name, dev_sprintf(fmt, what)) + dev_part_strct_entry(tsv, ".prog", id, NULL, name, dev_sprintf(fmt, what), pgm->comments) #define _if_pgmout(cmp, fmt, component) do { \ if(!base || cmp(base->component, pgm->component)) \ - 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), pgm->comments); \ } while(0) -// Result must be a malloc()ed string +// Result must be a malloc'd 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); \ + dev_part_strct_entry(tsv, ".prog", id, NULL, #component, result, pgm->comments); \ } while(0) + #define _partout(fmt, component) \ - 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), p->comments) #define _if_partout(cmp, fmt, component) do { \ if(!base || cmp(base->component, p->component)) \ - 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), p->comments); \ } while(0) #define _if_n_partout(cmp, n, fmt, component) do { \ if(!base || cmp(base->component, p->component, n)) \ - 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), p->comments); \ } while(0) -// Result must be a malloc()ed string +// Result must be a malloc'd string #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, p->comments) -// Result must be a malloc()ed string +// Result must be a malloc'd 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); \ + dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, result, p->comments); \ } while(0) -// Result must be a malloc()ed string +// Result must be a malloc'd 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); \ + dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, result, p->comments); \ } while(0) #define _memout(fmt, component) \ - 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), m->comments) #define _if_memout(cmp, fmt, component) do { \ if(!bm || cmp(bm->component, m->component)) \ - 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), m->comments); \ } while(0) -// Result must be a malloc()ed string +// Result must be a malloc'd string #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, m->comments) -// Result must be a malloc()ed string +// Result must be a malloc'd 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); \ + dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, result, m->comments); \ } while(0) #define _memout_yn(component) \ - dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, cfg_strdup("_memout_yn()", m->component? "yes": "no")) + dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, cfg_strdup("_memout_yn()", m->component? "yes": "no"), m->comments) #define _if_memout_yn(component) do { \ if(!bm || bm->component != m->component) \ - dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, cfg_strdup("_if_memout_yn()", m->component? "yes": "no")); \ + dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, cfg_strdup("_if_memout_yn()", m->component? "yes": "no"), m->comments); \ } while(0) #define _flagout(mask, name) \ @@ -132,8 +133,8 @@ static int dev_message(int msglvl, const char *fmt, ...); _partout_str(cfg_strdup("_if_flagout()", p->flags & (mask)? "yes": "no"), name); \ } while(0) -// Result must be a malloc()ed string +// Result must be a malloc'd string #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, NULL) #endif diff --git a/src/lexer.l b/src/lexer.l index 47c3cb25..a69130d3 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -39,6 +39,15 @@ #define YYERRCODE 256 #endif +/* capture lvalue keywords to associate comments with that assignment */ +#define ccap() capture_lvalue_kw(yytext, cfg_lineno) + +static void adjust_cfg_lineno(const char *p) { + while(*p) + if(*p++ == '\n') + cfg_lineno++; +} + %} DIGIT [0-9] @@ -71,14 +80,19 @@ SIGN [+-] 0x{HEXDIGIT}+ { yylval = hexnumber(yytext); return TKN_NUMBER; } -#[^\n]*\n+ { /* record and skip # comments */ - capture_comment_str(yytext); - for(int i=0; yytext[i]; i++) { - if(yytext[i] == '\n') - cfg_lineno++; - } +#\n#\ PROGRAMMER\ DEFINITIONS\n#\n+ { /* Record comments so far as prologue and skip */ + cfg_capture_prologue(); + adjust_cfg_lineno(yytext); } +#\n#\ PART\ DEFINITIONS\n#\n+ { /* Ignore part definions header */ + adjust_cfg_lineno(yytext); +} + +[ \t]*#[^\n]*\n+ { /* Record and skip # comments including preceding white space */ + capture_comment_str(yytext, cfg_lineno); + adjust_cfg_lineno(yytext); +} "/*" { /* The following eats multiline C style comments, they are not captured */ int c; @@ -108,137 +122,137 @@ SIGN [+-] alias { yylval=NULL; return K_ALIAS; } -allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; } -avr910_devcode { yylval=NULL; return K_AVR910_DEVCODE; } +allowfullpagebitstream { yylval=NULL; ccap(); return K_ALLOWFULLPAGEBITSTREAM; } +avr910_devcode { yylval=NULL; ccap(); return K_AVR910_DEVCODE; } bank_size { yylval=NULL; return K_PAGE_SIZE; } banked { yylval=NULL; return K_PAGED; } -baudrate { yylval=NULL; return K_BAUDRATE; } -blocksize { yylval=NULL; return K_BLOCKSIZE; } -bs2 { yylval=NULL; return K_BS2; } -buff { yylval=NULL; return K_BUFF; } -bytedelay { yylval=NULL; return K_BYTEDELAY; } -chip_erase { yylval=new_token(K_CHIP_ERASE); return K_CHIP_ERASE; } -chip_erase_delay { yylval=NULL; return K_CHIP_ERASE_DELAY; } -chiperasepolltimeout { yylval=NULL; return K_CHIPERASEPOLLTIMEOUT; } -chiperasepulsewidth { yylval=NULL; return K_CHIPERASEPULSEWIDTH; } -chiperasetime { yylval=NULL; return K_CHIPERASETIME; } -cmdexedelay { yylval=NULL; return K_CMDEXEDELAY; } -connection_type { yylval=NULL; return K_CONNTYPE; } +baudrate { yylval=NULL; ccap(); return K_BAUDRATE; } +blocksize { yylval=NULL; ccap(); return K_BLOCKSIZE; } +bs2 { yylval=NULL; ccap(); return K_BS2; } +buff { yylval=NULL; ccap(); return K_BUFF; } +bytedelay { yylval=NULL; ccap(); return K_BYTEDELAY; } +chip_erase { yylval=new_token(K_CHIP_ERASE); ccap(); return K_CHIP_ERASE; } +chip_erase_delay { yylval=NULL; ccap(); return K_CHIP_ERASE_DELAY; } +chiperasepolltimeout { yylval=NULL; ccap(); return K_CHIPERASEPOLLTIMEOUT; } +chiperasepulsewidth { yylval=NULL; ccap(); return K_CHIPERASEPULSEWIDTH; } +chiperasetime { yylval=NULL; ccap(); return K_CHIPERASETIME; } +cmdexedelay { yylval=NULL; ccap(); return K_CMDEXEDELAY; } +connection_type { yylval=NULL; ccap(); return K_CONNTYPE; } dedicated { yylval=new_token(K_DEDICATED); return K_DEDICATED; } default_bitclock { yylval=NULL; return K_DEFAULT_BITCLOCK; } default_parallel { yylval=NULL; return K_DEFAULT_PARALLEL; } default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; } default_serial { yylval=NULL; return K_DEFAULT_SERIAL; } default_spi { yylval=NULL; return K_DEFAULT_SPI; } -delay { yylval=NULL; return K_DELAY; } -desc { yylval=NULL; return K_DESC; } -family_id { yylval=NULL; return K_FAMILY_ID; } -devicecode { yylval=NULL; return K_DEVICECODE; } -eecr { yylval=NULL; return K_EECR; } +delay { yylval=NULL; ccap(); return K_DELAY; } +desc { yylval=NULL; ccap(); return K_DESC; } +devicecode { yylval=NULL; ccap(); return K_DEVICECODE; } +eecr { yylval=NULL; ccap(); return K_EECR; } eeprom { yylval=NULL; return K_EEPROM; } -eeprom_instr { yylval=NULL; return K_EEPROM_INSTR; } -enablepageprogramming { yylval=NULL; return K_ENABLEPAGEPROGRAMMING; } -errled { yylval=NULL; return K_ERRLED; } +eeprom_instr { yylval=NULL; ccap(); return K_EEPROM_INSTR; } +enablepageprogramming { yylval=NULL; ccap(); return K_ENABLEPAGEPROGRAMMING; } +errled { yylval=NULL; ccap(); return K_ERRLED; } +family_id { yylval=NULL; ccap(); return K_FAMILY_ID; } flash { yylval=NULL; return K_FLASH; } -flash_instr { yylval=NULL; return K_FLASH_INSTR; } -has_debugwire { yylval=NULL; return K_HAS_DW; } -has_jtag { yylval=NULL; return K_HAS_JTAG; } -has_pdi { yylval=NULL; return K_HAS_PDI; } -has_tpi { yylval=NULL; return K_HAS_TPI; } -has_updi { yylval=NULL; return K_HAS_UPDI; } -hventerstabdelay { yylval=NULL; return K_HVENTERSTABDELAY; } -hvleavestabdelay { yylval=NULL; return K_HVLEAVESTABDELAY; } -hvsp_controlstack { yylval=NULL; return K_HVSP_CONTROLSTACK; } -hvspcmdexedelay { yylval=NULL; return K_HVSPCMDEXEDELAY; } -hvupdi_support { yylval=NULL; return K_HVUPDI_SUPPORT; } -hvupdi_variant { yylval=NULL; return K_HVUPDI_VARIANT; } -id { yylval=NULL; return K_ID; } -idr { yylval=NULL; return K_IDR; } +flash_instr { yylval=NULL; ccap(); return K_FLASH_INSTR; } +has_debugwire { yylval=NULL; ccap(); return K_HAS_DW; } +has_jtag { yylval=NULL; ccap(); return K_HAS_JTAG; } +has_pdi { yylval=NULL; ccap(); return K_HAS_PDI; } +has_tpi { yylval=NULL; ccap(); return K_HAS_TPI; } +has_updi { yylval=NULL; ccap(); return K_HAS_UPDI; } +hventerstabdelay { yylval=NULL; ccap(); return K_HVENTERSTABDELAY; } +hvleavestabdelay { yylval=NULL; ccap(); return K_HVLEAVESTABDELAY; } +hvsp_controlstack { yylval=NULL; ccap(); return K_HVSP_CONTROLSTACK; } +hvspcmdexedelay { yylval=NULL; ccap(); return K_HVSPCMDEXEDELAY; } +hvupdi_support { yylval=NULL; ccap(); return K_HVUPDI_SUPPORT; } +hvupdi_variant { yylval=NULL; ccap(); return K_HVUPDI_VARIANT; } +id { yylval=NULL; ccap(); return K_ID; } +idr { yylval=NULL; ccap(); return K_IDR; } io { yylval=new_token(K_IO); return K_IO; } -is_at90s1200 { yylval=NULL; return K_IS_AT90S1200; } -is_avr32 { yylval=NULL; return K_IS_AVR32; } -latchcycles { yylval=NULL; return K_LATCHCYCLES; } -load_ext_addr { yylval=new_token(K_LOAD_EXT_ADDR); return K_LOAD_EXT_ADDR; } -loadpage_hi { yylval=new_token(K_LOADPAGE_HI); return K_LOADPAGE_HI; } -loadpage_lo { yylval=new_token(K_LOADPAGE_LO); return K_LOADPAGE_LO; } -max_write_delay { yylval=NULL; return K_MAX_WRITE_DELAY; } -mcu_base { yylval=NULL; return K_MCU_BASE; } -memory { yylval=NULL; return K_MEMORY; } -min_write_delay { yylval=NULL; return K_MIN_WRITE_DELAY; } -miso { yylval=NULL; return K_MISO; } -mode { yylval=NULL; return K_MODE; } -mosi { yylval=NULL; return K_MOSI; } +is_at90s1200 { yylval=NULL; ccap(); return K_IS_AT90S1200; } +is_avr32 { yylval=NULL; ccap(); return K_IS_AVR32; } +latchcycles { yylval=NULL; ccap(); return K_LATCHCYCLES; } +load_ext_addr { yylval=new_token(K_LOAD_EXT_ADDR); ccap(); return K_LOAD_EXT_ADDR; } +loadpage_hi { yylval=new_token(K_LOADPAGE_HI); ccap(); return K_LOADPAGE_HI; } +loadpage_lo { yylval=new_token(K_LOADPAGE_LO); ccap(); return K_LOADPAGE_LO; } +max_write_delay { yylval=NULL; ccap(); return K_MAX_WRITE_DELAY; } +mcu_base { yylval=NULL; ccap(); return K_MCU_BASE; } +memory { yylval=NULL; ccap(); return K_MEMORY; } +min_write_delay { yylval=NULL; ccap(); return K_MIN_WRITE_DELAY; } +miso { yylval=NULL; ccap(); return K_MISO; } +mode { yylval=NULL; ccap(); return K_MODE; } +mosi { yylval=NULL; ccap(); return K_MOSI; } no { yylval=new_token(K_NO); return K_NO; } NULL { yylval=NULL; return K_NULL; } num_banks { yylval=NULL; return K_NUM_PAGES; } -num_pages { yylval=NULL; return K_NUM_PAGES; } -nvm_base { yylval=NULL; return K_NVM_BASE; } -ocd_base { yylval=NULL; return K_OCD_BASE; } -ocdrev { yylval=NULL; return K_OCDREV; } -offset { yylval=NULL; return K_OFFSET; } -page_size { yylval=NULL; return K_PAGE_SIZE; } -paged { yylval=NULL; return K_PAGED; } -pagel { yylval=NULL; return K_PAGEL; } -parallel { yylval=NULL; return K_PARALLEL; } +num_pages { yylval=NULL; ccap(); return K_NUM_PAGES; } +nvm_base { yylval=NULL; ccap(); return K_NVM_BASE; } +ocd_base { yylval=NULL; ccap(); return K_OCD_BASE; } +ocdrev { yylval=NULL; ccap(); return K_OCDREV; } +offset { yylval=NULL; ccap(); return K_OFFSET; } +paged { yylval=NULL; ccap(); return K_PAGED; } +pagel { yylval=NULL; ccap(); return K_PAGEL; } +page_size { yylval=NULL; ccap(); return K_PAGE_SIZE; } +parallel { yylval=NULL; ccap(); return K_PARALLEL; } parent { yylval=NULL; return K_PARENT; } -part { yylval=NULL; return K_PART; } -pgm_enable { yylval=new_token(K_PGM_ENABLE); return K_PGM_ENABLE; } -pgmled { yylval=NULL; return K_PGMLED; } -pollindex { yylval=NULL; return K_POLLINDEX; } -pollmethod { yylval=NULL; return K_POLLMETHOD; } -pollvalue { yylval=NULL; return K_POLLVALUE; } -postdelay { yylval=NULL; return K_POSTDELAY; } -poweroffdelay { yylval=NULL; return K_POWEROFFDELAY; } -pp_controlstack { yylval=NULL; return K_PP_CONTROLSTACK; } -predelay { yylval=NULL; return K_PREDELAY; } -progmodedelay { yylval=NULL; return K_PROGMODEDELAY; } -programfusepolltimeout { yylval=NULL; return K_PROGRAMFUSEPOLLTIMEOUT; } -programfusepulsewidth { yylval=NULL; return K_PROGRAMFUSEPULSEWIDTH; } -programlockpolltimeout { yylval=NULL; return K_PROGRAMLOCKPOLLTIMEOUT; } -programlockpulsewidth { yylval=NULL; return K_PROGRAMLOCKPULSEWIDTH; } -programmer { yylval=NULL; return K_PROGRAMMER; } +part { yylval=NULL; ccap(); return K_PART; } +pgm_enable { yylval=new_token(K_PGM_ENABLE); ccap(); return K_PGM_ENABLE; } +pgmled { yylval=NULL; ccap(); return K_PGMLED; } +pollindex { yylval=NULL; ccap(); return K_POLLINDEX; } +pollmethod { yylval=NULL; ccap(); return K_POLLMETHOD; } +pollvalue { yylval=NULL; ccap(); return K_POLLVALUE; } +postdelay { yylval=NULL; ccap(); return K_POSTDELAY; } +poweroffdelay { yylval=NULL; ccap(); return K_POWEROFFDELAY; } +pp_controlstack { yylval=NULL; ccap(); return K_PP_CONTROLSTACK; } +predelay { yylval=NULL; ccap(); return K_PREDELAY; } +progmodedelay { yylval=NULL; ccap(); return K_PROGMODEDELAY; } +programfusepolltimeout { yylval=NULL; ccap(); return K_PROGRAMFUSEPOLLTIMEOUT; } +programfusepulsewidth { yylval=NULL; ccap(); return K_PROGRAMFUSEPULSEWIDTH; } +programlockpolltimeout { yylval=NULL; ccap(); return K_PROGRAMLOCKPOLLTIMEOUT; } +programlockpulsewidth { yylval=NULL; ccap(); return K_PROGRAMLOCKPULSEWIDTH; } +programmer { yylval=NULL; ccap(); return K_PROGRAMMER; } pseudo { yylval=new_token(K_PSEUDO); return K_PSEUDO; } -pwroff_after_write { yylval=NULL; return K_PWROFF_AFTER_WRITE; } -rampz { yylval=NULL; return K_RAMPZ; } -rdyled { yylval=NULL; return K_RDYLED; } -read { yylval=new_token(K_READ); return K_READ; } -read_hi { yylval=new_token(K_READ_HI); return K_READ_HI; } -read_lo { yylval=new_token(K_READ_LO); return K_READ_LO; } -readback { yylval=NULL; return K_READBACK; } -readback_p1 { yylval=NULL; return K_READBACK_P1; } -readback_p2 { yylval=NULL; return K_READBACK_P2; } -readsize { yylval=NULL; return K_READSIZE; } -reset { yylval=new_token(K_RESET); return K_RESET; } -resetdelay { yylval=NULL; return K_RESETDELAY; } -resetdelayms { yylval=NULL; return K_RESETDELAYMS; } -resetdelayus { yylval=NULL; return K_RESETDELAYUS; } -retry_pulse { yylval=NULL; return K_RETRY_PULSE; } -sck { yylval=new_token(K_SCK); return K_SCK; } -serial { yylval=NULL; return K_SERIAL; } -signature { yylval=NULL; return K_SIGNATURE; } -size { yylval=NULL; return K_SIZE; } +pwroff_after_write { yylval=NULL; ccap(); return K_PWROFF_AFTER_WRITE; } +rampz { yylval=NULL; ccap(); return K_RAMPZ; } +rdyled { yylval=NULL; ccap(); return K_RDYLED; } +read { yylval=new_token(K_READ); ccap(); return K_READ; } +read_hi { yylval=new_token(K_READ_HI); ccap(); return K_READ_HI; } +read_lo { yylval=new_token(K_READ_LO); ccap(); return K_READ_LO; } +readback { yylval=NULL; ccap(); return K_READBACK; } +readback_p1 { yylval=NULL; ccap(); return K_READBACK_P1; } +readback_p2 { yylval=NULL; ccap(); return K_READBACK_P2; } +readsize { yylval=NULL; ccap(); return K_READSIZE; } +reset { yylval=new_token(K_RESET); ccap(); return K_RESET; } +resetdelay { yylval=NULL; ccap(); return K_RESETDELAY; } +resetdelayms { yylval=NULL; ccap(); return K_RESETDELAYMS; } +resetdelayus { yylval=NULL; ccap(); return K_RESETDELAYUS; } +retry_pulse { yylval=NULL; ccap(); return K_RETRY_PULSE; } +sck { yylval=new_token(K_SCK); ccap(); return K_SCK; } +serial { yylval=NULL; ccap(); return K_SERIAL; } +signature { yylval=NULL; ccap(); return K_SIGNATURE; } +size { yylval=NULL; ccap(); return K_SIZE; } spi { yylval=NULL; return K_SPI; } -spmcr { yylval=NULL; return K_SPMCR; } -stabdelay { yylval=NULL; return K_STABDELAY; } -stk500_devcode { yylval=NULL; return K_STK500_DEVCODE; } -synchcycles { yylval=NULL; return K_SYNCHCYCLES; } -synchloops { yylval=NULL; return K_SYNCHLOOPS; } -timeout { yylval=NULL; return K_TIMEOUT; } -togglevtg { yylval=NULL; return K_TOGGLEVTG; } -type { yylval=NULL; return K_TYPE; } +spmcr { yylval=NULL; ccap(); return K_SPMCR; } +stabdelay { yylval=NULL; ccap(); return K_STABDELAY; } +stk500_devcode { yylval=NULL; ccap(); return K_STK500_DEVCODE; } +synchcycles { yylval=NULL; ccap(); return K_SYNCHCYCLES; } +synchloops { yylval=NULL; ccap(); return K_SYNCHLOOPS; } +timeout { yylval=NULL; ccap(); return K_TIMEOUT; } +togglevtg { yylval=NULL; ccap(); return K_TOGGLEVTG; } +type { yylval=NULL; ccap(); return K_TYPE; } usb { yylval=NULL; return K_USB; } -usbdev { yylval=NULL; return K_USBDEV; } -usbpid { yylval=NULL; return K_USBPID; } -usbproduct { yylval=NULL; return K_USBPRODUCT; } -usbsn { yylval=NULL; return K_USBSN; } -usbvendor { yylval=NULL; return K_USBVENDOR; } -usbvid { yylval=NULL; return K_USBVID; } -vcc { yylval=NULL; return K_VCC; } -vfyled { yylval=NULL; return K_VFYLED; } -write { yylval=new_token(K_WRITE); return K_WRITE; } -write_hi { yylval=new_token(K_WRITE_HI); return K_WRITE_HI; } -write_lo { yylval=new_token(K_WRITE_LO); return K_WRITE_LO; } -writepage { yylval=new_token(K_WRITEPAGE); return K_WRITEPAGE; } +usbdev { yylval=NULL; ccap(); return K_USBDEV; } +usbpid { yylval=NULL; ccap(); return K_USBPID; } +usbproduct { yylval=NULL; ccap(); return K_USBPRODUCT; } +usbsn { yylval=NULL; ccap(); return K_USBSN; } +usbvendor { yylval=NULL; ccap(); return K_USBVENDOR; } +usbvid { yylval=NULL; ccap(); return K_USBVID; } +vcc { yylval=NULL; ccap(); return K_VCC; } +vfyled { yylval=NULL; ccap(); return K_VFYLED; } +write { yylval=new_token(K_WRITE); ccap(); return K_WRITE; } +write_hi { yylval=new_token(K_WRITE_HI); ccap(); return K_WRITE_HI; } +write_lo { yylval=new_token(K_WRITE_LO); ccap(); return K_WRITE_LO; } +writepage { yylval=new_token(K_WRITEPAGE); ccap(); return K_WRITEPAGE; } yes { yylval=new_token(K_YES); return K_YES; } "," { yylval = NULL; pyytext(); return TKN_COMMA; } diff --git a/src/libavrdude.h b/src/libavrdude.h index cbbc8a79..d15677eb 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -215,7 +215,8 @@ typedef struct opcode { typedef struct avrpart { const char * desc; /* long part name */ const char * id; /* short part name */ - const char * parent_id; /* parent id if set, for -p.../s */ + LISTID comments; // Used by developer options -p*/[ASsr...] + const char * parent_id; /* Used by developer options */ const char * family_id; /* family id in the SIB (avr8x) */ int hvupdi_variant; /* HV pulse on UPDI pin, no pin or RESET pin */ int stk500_devcode; /* stk500 device code */ @@ -285,6 +286,7 @@ typedef struct avrpart { #define AVR_MEMDESCLEN 64 typedef struct avrmem { const char *desc; /* memory description ("flash", "eeprom", etc) */ + LISTID comments; // Used by developer options -p*/[ASsr...] int paged; /* page addressed (e.g. ATmega flash) */ int size; /* total memory size in bytes */ int page_size; /* size of memory page (if page addressed) */ @@ -684,7 +686,8 @@ typedef struct programmer_t { LISTID id; const char *desc; void (*initpgm)(struct programmer_t *pgm); - const char *parent_id; // Used by developer options -c*/[sr...] + LISTID comments; // Used by developer options -c*/[ASsr...] + const char *parent_id; // Used by developer options struct pindef_t pin[N_PINS]; conntype_t conntype; int baudrate; diff --git a/src/main.c b/src/main.c index 2487faa7..ae9e5ea8 100644 --- a/src/main.c +++ b/src/main.c @@ -244,6 +244,14 @@ static void replace_backslashes(char *s) } } +// Return 2 if string is * or starts with */, 1 if string contains /, 0 otherwise +static int dev_opt(char *str) { + return + !str? 0: + !strcmp(str, "*") || !strncmp(str, "*/", 2)? 2: + !!strchr(str, '/'); +} + /* * main routine @@ -752,20 +760,14 @@ int main(int argc, char * argv []) bitclock = default_bitclock; } + // Developer options to print parts and/or programmer entries of avrdude.conf + int dev_opt_c = dev_opt(programmer); // -c /[sSArt] + int dev_opt_p = dev_opt(partdesc); // -p /[dsSArcow*t] - int dev_opts = 0; - // Developer option -c /[ASsrt] prints programmer description(s) and exits - if(programmer && (strcmp(programmer, "*") == 0 || strchr(programmer, '/'))) { - dev_output_pgm_defs(cfg_strdup("main()", programmer)); - dev_opts = 1; - } - // Developer option -p /[dASsrcow*t] prints part description(s) and exits - if(partdesc && (strcmp(partdesc, "*") == 0 || strchr(partdesc, '/'))) { - dev_output_part_defs(partdesc); - dev_opts = 1; - } - if(dev_opts) + if(dev_opt_c || dev_opt_p) { // See -c/h and or -p/h + dev_output_pgm_part(dev_opt_c, programmer, dev_opt_p, partdesc); exit(0); + } avrdude_message(MSG_NOTICE, "\n"); From 8420b272335a0db7c86162ffe77f0692dfb18235 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Fri, 12 Aug 2022 14:58:21 +0100 Subject: [PATCH 16/19] Address compiler warnings in 4 source files --- src/developer_opts.c | 9 +++------ src/jtagmkII.c | 2 -- src/ser_win32.c | 6 +++--- src/stk500v2.c | 10 +++++++--- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/developer_opts.c b/src/developer_opts.c index e0c274b9..dc7a4063 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -402,14 +402,11 @@ static int avrpart_deep_copy(AVRPARTdeep *d, const AVRPART *p) { // Copy over desc, id, and family_id memset(d->descbuf, 0, sizeof d->descbuf); - if(d->descbuf) - strncpy(d->descbuf, p->desc, sizeof d->descbuf-1); + strncpy(d->descbuf, p->desc, sizeof d->descbuf-1); memset(d->idbuf, 0, sizeof d->idbuf); - if(d->idbuf) - strncpy(d->idbuf, p->id, sizeof d->idbuf-1); + strncpy(d->idbuf, p->id, sizeof d->idbuf-1); memset(d->family_idbuf, 0, sizeof d->family_idbuf); - if(d->family_idbuf) - strncpy(d->family_idbuf, p->family_id, sizeof d->family_idbuf-1); + strncpy(d->family_idbuf, p->family_id, sizeof d->family_idbuf-1); // Zap address values d->base.desc = NULL; diff --git a/src/jtagmkII.c b/src/jtagmkII.c index f52f3bc3..ef45ee22 100644 --- a/src/jtagmkII.c +++ b/src/jtagmkII.c @@ -488,7 +488,6 @@ static int jtagmkII_recv_frame(PROGRAMMER * pgm, unsigned char **msg, int rv; unsigned char c, *buf = NULL, header[8]; unsigned short r_seqno = 0; - unsigned short checksum = 0; struct timeval tv; double timeoutval = 100; /* seconds */ @@ -521,7 +520,6 @@ static int jtagmkII_recv_frame(PROGRAMMER * pgm, unsigned char **msg, if (serial_recv(&pgm->fd, &c, 1) != 0) goto timedout; } - checksum ^= c; if (state < sDATA) header[headeridx++] = c; diff --git a/src/ser_win32.c b/src/ser_win32.c index fa4d7aba..970a3ecb 100644 --- a/src/ser_win32.c +++ b/src/ser_win32.c @@ -393,7 +393,7 @@ static int net_send(union filedescriptor *fd, const unsigned char * buf, size_t } while (len) { - rc = send(fd->ifd, p, (len > 1024) ? 1024 : len, 0); + rc = send(fd->ifd, (const char *) p, (len > 1024)? 1024: len, 0); if (rc < 0) { FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | @@ -527,7 +527,7 @@ reselect: } } - rc = recv(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len, 0); + rc = recv(fd->ifd, (char *) p, (buflen - len > 1024)? 1024: buflen - len, 0); if (rc < 0) { FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | @@ -693,7 +693,7 @@ static int net_drain(union filedescriptor *fd, int display) } } - rc = recv(fd->ifd, &buf, 1, 0); + rc = recv(fd->ifd, (char *) &buf, 1, 0); if (rc < 0) { FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | diff --git a/src/stk500v2.c b/src/stk500v2.c index a50fda4c..8f16ae41 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -3093,12 +3093,14 @@ static int stk500v2_setparm_real(PROGRAMMER * pgm, unsigned char parm, unsigned static int stk500v2_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned char value) { - unsigned char current_value; + unsigned char current_value = value; int res; res = stk500v2_getparm(pgm, parm, ¤t_value); - if (res < 0) + if (res < 0) { avrdude_message(MSG_INFO, "%s: Unable to get parameter 0x%02x\n", progname, parm); + return -1; + } // don't issue a write if the correct value is already set. if (value == current_value) { @@ -3245,7 +3247,7 @@ f_to_kHz_MHz(double f, const char **unit) static void stk500v2_print_parms1(PROGRAMMER * pgm, const char * p) { - unsigned char vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration =0; //XXX 0 is not correct, check caller + unsigned char vtarget = 0, vadjust = 0, osc_pscale = 0, osc_cmatch = 0, sck_duration =0; //XXX 0 is not correct, check caller unsigned int sck_stk600, clock_conf, dac, oct, varef; unsigned char vtarget_jtag[4]; int prescale; @@ -3253,6 +3255,8 @@ static void stk500v2_print_parms1(PROGRAMMER * pgm, const char * p) const char *unit; void *mycookie; + memset(vtarget_jtag, 0, sizeof vtarget_jtag); + if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII) { mycookie = pgm->cookie; pgm->cookie = PDATA(pgm)->chained_pdata; From 533feec4ede1fa0502de01183cfbcdd570e3005f Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Fri, 12 Aug 2022 15:52:51 +0100 Subject: [PATCH 17/19] Revert grammar to remove introduced shift/reduce conflicts --- src/config_gram.y | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/config_gram.y b/src/config_gram.y index 2c3504f2..c4c144a7 100644 --- a/src/config_gram.y +++ b/src/config_gram.y @@ -1356,8 +1356,7 @@ yesno : mem_specs : mem_spec TKN_SEMI | mem_alias TKN_SEMI | - mem_specs mem_spec TKN_SEMI | - /* empty */ + mem_specs mem_spec TKN_SEMI ; From c9736a9db5f1c0aae4023a32ef905a6d9ea6bc1e Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sat, 13 Aug 2022 20:51:12 +0100 Subject: [PATCH 18/19] Specifying the full memory name now always works ... even if a memory with longer name and same initial part exists --- src/avrpart.c | 61 +++++++++++++++------------------------------------ 1 file changed, 18 insertions(+), 43 deletions(-) diff --git a/src/avrpart.c b/src/avrpart.c index 526d0503..df514f1d 100644 --- a/src/avrpart.c +++ b/src/avrpart.c @@ -423,88 +423,63 @@ void avr_free_memalias(AVRMEM_ALIAS *m) { AVRMEM_ALIAS *avr_locate_memalias(const AVRPART *p, const char *desc) { AVRMEM_ALIAS * m, * match; LNODEID ln; - int matches; + int matches, exact; int l; if(!p || !desc || !p->mem_alias) return NULL; l = strlen(desc); - matches = 0; + matches = exact = 0; match = NULL; for (ln=lfirst(p->mem_alias); ln; ln=lnext(ln)) { m = ldata(ln); - if (strncmp(desc, m->desc, l) == 0) { + if (strncmp(m->desc, desc, l) == 0) { // Partial initial match match = m; matches++; + if(m->desc[l] == 0) // Exact match between arg and memory + exact++; } } - if (matches == 1) - return match; - - return NULL; + return exact == 1 || matches == 1? match: NULL; } AVRMEM *avr_locate_mem_noalias(const AVRPART *p, const char *desc) { AVRMEM * m, * match; LNODEID ln; - int matches; + int matches, exact; int l; if(!p || !desc || !p->mem) return NULL; l = strlen(desc); - matches = 0; + matches = exact = 0; match = NULL; for (ln=lfirst(p->mem); ln; ln=lnext(ln)) { m = ldata(ln); - if (strncmp(desc, m->desc, l) == 0) { + if (strncmp(m->desc, desc, l) == 0) { // Partial initial match match = m; matches++; + if(m->desc[l] == 0) // Exact match between arg and memory + exact++; } } - if (matches == 1) - return match; - - return NULL; + return exact == 1 || matches == 1? match: NULL; } AVRMEM *avr_locate_mem(const AVRPART *p, const char *desc) { - AVRMEM * m, * match; - AVRMEM_ALIAS * alias; - LNODEID ln; - int matches; - int l; + AVRMEM *m = avr_locate_mem_noalias(p, desc); - if(!p || !desc) - return NULL; + if(m) + return m; - l = strlen(desc); - matches = 0; - match = NULL; - if(p->mem) { - for (ln=lfirst(p->mem); ln; ln=lnext(ln)) { - m = ldata(ln); - if (strncmp(desc, m->desc, l) == 0) { - match = m; - matches++; - } - } - } - - if (matches == 1) - return match; - - /* not yet found: look for matching alias name */ - alias = avr_locate_memalias(p, desc); - if (alias != NULL) - return alias->aliased_mem; - - return NULL; + // Not yet found: look for matching alias name + AVRMEM_ALIAS *a = avr_locate_memalias(p, desc); + return a? a->aliased_mem: NULL; } AVRMEM_ALIAS *avr_find_memalias(const AVRPART *p, const AVRMEM *m_orig) { From 297740db0e078e90387507e849cb5a7b5ded2c09 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sat, 13 Aug 2022 22:57:54 +0100 Subject: [PATCH 19/19] Stop listing programmers where id starts with . --- src/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main.c b/src/main.c index ae9e5ea8..c135ef00 100644 --- a/src/main.c +++ b/src/main.c @@ -140,6 +140,10 @@ static void list_programmers_callback(const char *name, const char *desc, void *cookie) { struct list_walk_cookie *c = (struct list_walk_cookie *)cookie; + + if (*name == 0 || *name == '.') + return; + if (verbose){ fprintf(c->f, "%s%-16s = %-30s [%s:%d]\n", c->prefix, name, desc, cfgname, cfglineno);