linuxubuntuawklibopencm3

AWK different versions behavior when using regex pattern


Background:

Recently I have tried to build libopencm3-examples on Ubuntu 14.04 and encountered a build error (while for Ubuntu 16.04.1 LTS it works ok). I started digging in order to find the reason. As I have discovered, libopencm3 uses specific linker script generator:

see libopencm3-examples/libopencm3/ld/README

the purpose of this tool is to pass target micro controller specific defines to linker script template. So it use preprocessor under template script and pass target specific parameters like so:

-D_FPU=hard-fpv5-sp-d16 -D_ROM_OFF=0x08000000 -D_RAM_OFF=0x20000000

to retrieve this parameters awk script is used.

./libopencm3/scripts/genlink.awk

for generating -D_XXX keys this script operates under device database ./libopencm3/ld/devices.data like so:

awk -v PAT="$(DEVICE)" -v MODE="DEFS" -f $(OPENCM3_DIR)/scripts/genlink.awk $(OPENCM3_DIR)/ld/devices.data

Question:

The awk script part, extracting the defines info from database looks like this:

...
for (i = 3; i <= NF; i = i + 1) {
...
    else if ($i ~ /[[:upper:]]*=/) {
        if ("DEFS" == MODE)
            printf "-D_%s ",$i;
    }
}

the row in database, processed by the script:

stm32f3[01]3?c* stm32f3ccm ROM=256K RAM=40K CCM=8K

What confuse me, is that the proposed pattern (/[[:upper:]]*=/) should match [ROM]=256K f.e., but not ROM=256K (yes?). Anyhow, as i already mentioned /[[:upper:]]*=/ works for ubuntu 16.04 (GNU Awk 4.1.3) (Why?), while for 14.04 i needed to change /[[:upper:]]*=/ -> /[:upper:]*=/ to force it work (is this a bug or what?). Am I missing something?


Solution

  • No, the square bracket character is special in regex. If you want to match it literally, use \[. The expression [:upper:] inside square brackets refers to the character class consisting of upper-case characters. I'm guessing you want

    /[][:upper:][]+=/
    

    to form a bracket expression consisting of literal closing square bracket, uppercase characters, and literal opening square bracket. Notice also the switch to + instead of * to prevent matching on a lone equals sign (* means zero or more, so with zero repetitions, it would match on any equals sign).

    Possibly the Awk you have doesn't support POSIX character classes at all. Then, you could replace [:upper:] with A-Z though it won't then match locale-sensitively.