UUID as Array Keys strangely not possible

2019-01-22 Thread Robert White

Howdy,

The following cannot work because, for some reason, the array subscript 
parser insists on doing math on array indices even when the array is 
associative instead of numeric


typeset -A UUID_TABLE
...
UUID_TABLE+=( [${SOME_UUID}]=${SOME_VALUE} )
...
some_command ${UUID_TABLE[${SOME_UUID}]}

The parser and evaluator insist on doing math on ${SOME_UUID} no matter 
how its quoted or whatever. This seems extremely wrong.


At a minimum putting the index in double quotes should suppress the 
arithmetic evaluation. In the ideal the decision to math-or-not decision 
should happen after the array type is known, thought that's probably too 
hard.


Alternately some sort of builtin hash function to map complex strings 
into usable associative array indexes would be nice.


UUIDs are simply too useful and common in current systems to sustain 
their current second-class status.


(DISCLAIMER: I'm not a subscriber to this list.)



Re: UUID as Array Keys strangely not possible

2019-01-25 Thread Robert White

On 1/22/19 10:23 PM, Chet Ramey wrote:

On 1/22/19 3:32 PM, Robert White wrote:

Howdy,

The following cannot work because, for some reason, the array subscript
parser insists on doing math on array indices even when the array is
associative instead of numeric

typeset -A UUID_TABLE
...
UUID_TABLE+=( [${SOME_UUID}]=${SOME_VALUE} )
...
some_command ${UUID_TABLE[${SOME_UUID}]}

The parser and evaluator insist on doing math on ${SOME_UUID} no matter how
its quoted or whatever. This seems extremely wrong.


Do you have some sample UUID data to test this with?

I'm going to have to provisionally withdraw this report. The problem 
only seems to happen in the custom /init script in my initramfs. Trying 
to recreate it with a simpler script (and the same bash binary) on a 
fully running system using the the UUIDs I collected with blkid doesn't 
have a problem at all. So something "mysterious" is going on.


The initscript is part of https://sourceforge.net/projects/underdog/ (if 
you care) and is part of my attempt to build a concordance of UUID to 
device to manager (e.g. lvm vs mdadm vs whatever) app. It works well 
except when it doesn't.


Thanks for the prompt response. If I isolate the test case or the issue 
in general I'll be back. Even just to say never mind if I find a super 
stupid mistake. 8-)


--Rob White.



Re: UUID as Array Keys strangely not possible

2019-01-25 Thread Robert White

On 1/26/19 4:37 AM, Dennis Williamson wrote:

On Fri, Jan 25, 2019, 9:51 PM Robert White 
On 1/22/19 10:23 PM, Chet Ramey wrote:

On 1/22/19 3:32 PM, Robert White wrote:

Howdy,

The following cannot work because, for some reason, the array subscript
parser insists on doing math on array indices even when the array is
associative instead of numeric

typeset -A UUID_TABLE
...
UUID_TABLE+=( [${SOME_UUID}]=${SOME_VALUE} )
...
some_command ${UUID_TABLE[${SOME_UUID}]}

The parser and evaluator insist on doing math on ${SOME_UUID} no matter

how

its quoted or whatever. This seems extremely wrong.


Do you have some sample UUID data to test this with?


I'm going to have to provisionally withdraw this report. The problem
only seems to happen in the custom /init script in my initramfs. Trying
to recreate it with a simpler script (and the same bash binary) on a
fully running system using the the UUIDs I collected with blkid doesn't
have a problem at all. So something "mysterious" is going on.

The initscript is part of https://sourceforge.net/projects/underdog/ (if
you care) and is part of my attempt to build a concordance of UUID to
device to manager (e.g. lvm vs mdadm vs whatever) app. It works well
except when it doesn't.

Thanks for the prompt response. If I isolate the test case or the issue
in general I'll be back. Even just to say never mind if I find a super
stupid mistake. 8-)

--Rob White.



I'm not going to try to do a full code review. It took me more time than I
was willing to spend already to find a file that has an associative array
referring to UUIDs in the first place and to put this message together.

Here are a few comments about prototype/init:

In the global scope UUID_TABLE is declared as an indexed array at one point
then an associative array later.

In the get_ (something) function an array element is set violating
separation of get and set.

In that same function, a max_index variable is set to the highest index of
a numeric array then the array is iterated using a C-style for loop. Arrays
in Bash are sparse and the correct way to iterate is to step over the
elements or the indices.

for element in "${array[@]}"

for index in "${!array[@]}"

But it seems you just want to add an element.

array+=(element)

There is a variable called AA. I didn't look to see if that means something
but I shouldn't have to. A better name is needed.

Forgive me if I misunderstood anything. It was just a cursory once over.

  Also, I didn't immediately notice what the UUID indexing problem initially
reported is caused by. Except that I played with an indexed array with a
UUID-like index. In that case the index *is* evaluated mathematically so
this may be your problem. That makes sense based on the redefinition I
mentioned above since the second declare will produce an error without
affecting the array.






Yeah, that was me trying to hack around the UUID problem.

I tried to reduce the UUID index errors into a meta index where I look 
for the UUID in an indexed array and append it to the array if not 
found, and then use that index as the index elsewhere. It's a dumb trick 
that I used once in another environment (NexExpert, circa 1995 if you 
care) that didn't give me valid associative arrays.


The script as it currently exists is currently a confused abortion of 
hackery surrounding the original subscript errors.


But it started because just using the UUIDs as the associative array was 
crashing... but only on some UUIDs.


It started clean but it got ugly damn fast when the UUID errors initally 
showed up.


(so the get_ is a find-or-append-then-return-index() nonsense thing.)

It turned into a game of wac-a-mole.

Like I said, it got ugly. ha ha ha.

I've now got to back out the worst of the hacks and figure out why the 
original ${DEVICE_TABLE[$UUID]} style indexing failed in the init script 
when it clearly works with my collected UUIDs in regular user contexts.


I've already gone through and replaced or refactored all the 
double-square-bracket evaluations with single-square-bracket 
expressions, and otherwise looked for any explicit arithmatic contexts 
that might be confusing the issue.


The current state is hideous, which is why I need to back out the hacks; 
but the ugly hacks went in because of the indexing errors, so something 
is fishy.


--Rob.



General Associative Array problem -- Was: UUID as Array Keys strangely not possible

2019-02-22 Thread Robert White
Consider the script at the end of this email. It's effectively 
impossible to get   or  to accept the various values.


Either that or I am doing something incredibly stupid.

(It took me a while to factor this down and try virtually every 
workaround that would not involve writing external files.)



#!/bin/bash -f


# These three arrays never get values no matter what
typeset -A 
typeset -A 
typeset -A 

typeset -A INLINE
typeset -A INFUNC

function testfunc() {
  eval INFUNC=( $( blkid /dev/${RECORD[3]} -o export | sed -e 's;\\ 
;_;' -e 's;\(.*\)=;[\1]=;' ) )

  echo "Trying: +=( [${INFUNC[UUID]}]=boo )"
  eval +=( [${INFUNC[UUID]}]=boo )
}

tail --lines=+3 /proc/partitions | grep -v ram |
while read -a RECORD
do
  echo "Trying /dev/${RECORD[3]}"
  testfunc ${RECORD[3]}

  VV=$( blkid /dev/${RECORD[3]} -o export | sed -e 's;\\ ;_;' -e 
's;\(.*\)=;[\1]=;' )

  eval INLINE=( ${VV} )
  if [ ${INLINE[UUID]} ]
  then
    echo "Trying: [${INLINE[UUID]}]=boo"
    eval [${INLINE[UUID]}]=boo
  fi
  echo "INLINE Keys: " "${!INLINE[@]}" = "${INLINE[@]}"
  echo "INFUNC Keys: " "${!INFUNC[@]}" = "${INFUNC[@]}"
  for AA
  in "${!INLINE[@]}"
  do
    if [ ${AA} == UUID ]
    then
  echo "Trying: [${INLINE[$AA]}]=${INLINE[DEVNAME]}"
  [${INLINE[$AA]}]=${INLINE[DEVNAME]}
    fi
  done
  echo
done

echo " Keys: " "${![@]}" = "${[@]}"
echo " Keys: " "${![@]}" = "${[@]}"
echo " Keys: " "${![@]}" = "${[@]}"





Re: General Associative Array problem -- Was: UUID as Array Keys strangely not possible

2019-02-22 Thread Robert White

On 2/22/19 4:17 PM, Eduardo Bustamante wrote:

On Fri, Feb 22, 2019 at 3:24 AM Robert White  wrote:
(...)

tail --lines=+3 /proc/partitions | grep -v ram |
while read -a RECORD
do

(...)

  eval [${INLINE[UUID]}]=boo

(...)

done

echo " Keys: " "${![@]}" = "${[@]}"
echo " Keys: " "${![@]}" = "${[@]}"
echo " Keys: " "${![@]}" = "${[@]}"


The `while' loop executes in a subshell and you're not using
`lastpipe'. See: https://mywiki.wooledge.org/BashFAQ/024

As a general recommendation: when submitting bug reports, try to
simplify things as much as possible, e.g.:

* Replace the `blkid' command invokation with a `printf' (not everyone
has the same block devices, nor runs Linux)
* Replace `/proc/partitions' with a copy of its contents (again, not
everyone has the same files in their systems, makes it impossible to
reproduce what you're experiencing)
* Remove the  and  arrays, we only need a sample case to
understand what's going on, not three
* Remove the sed commands, you're going to be using static values
(`printf') anyways
* Does the `set -f' at the top of the file have any effect in the
outcome in this particular case? no? then remove it
* I think you get the idea.


Just to help you understand my perspective, this is what I see when I
try to troubleshoot your script (a bunch of errors), that doesn't
really help me help you:

dualbus@system76-pc:~$ shellcheck foo.sh

In foo.sh line 12:
function testfunc() {
^-- SC1009: The mentioned syntax error was in this function.
 ^-- SC1073: Couldn't parse this brace group. Fix
to allow more checks.


In foo.sh line 13:
eval INFUNC=( $( blkid /dev/${RECORD[3]} -o export | sed -e 's;\\
^-- SC1036: '(' is invalid here. Did you forget to escape it?
^-- SC1056: Expected a '}'. If you have one, try a ; or
\n in front of it.
^-- SC1072: Missing '}'. Fix any mentioned problems and
try again.
^-- SC1098: Quote/escape special characters when using
eval, e.g. eval "a=(b)".


Your syntax checker is straight tripping on that SC1036 error dude. 
Array assignment using ARRAYNAME=( expression ) is completely legal and 
correct with or without the eval. The structure even allows for line 
continuation just like pipelines


ARRAYNAME=(
)

Same for the error emitted for using the "function" keyord

function somename() {
}

It does look like it got line-wrapped to death in the sed, but according 
to my sent items directory that happened after it left here. So my bad 
for lack of attachment.


I get your point for blkid and /proc/partitions. I was getting 
frustrated since I'd tried all three forms of substitution I didn't know 
if the function calls, the evaluation order, or the expansions were to 
blame so I included all three contexts.


Turns out I've been doing the pipe-while-read thing blithely for a good 
twenty years now (going back to the borne shell on SVR4) and never 
thought about the pipeline itself.


So I was right, for stupid definitions of right, when I wondered if I 
was missing something incredibly obvious. /sigh. 8-)


Thanks for all the help.

--Rob.