* typeset -p output gives shows variables which can't be read back in @ 2011-02-27 11:44 Rocky Bernstein 2011-02-27 21:01 ` Bart Schaefer 0 siblings, 1 reply; 8+ messages in thread From: Rocky Bernstein @ 2011-02-27 11:44 UTC (permalink / raw) To: zsh-workers [-- Attachment #1: Type: text/plain, Size: 2027 bytes --] I would like to save to a file shell variables so that I can run a nested zsh and then read these back in. It is becoming a bit of a challenge because this in the output: typeset -i10 -r !=0 typeset -i10 -r '#'=0 typeset -i10 -r '$'=15221 typeset -ar '*' *=() typeset -r -=569Xfy typeset 0=_Dbg_do_shell typeset -i10 -r '?'=0 typeset -ar @ @=() typeset -rx _=-p Failing a better solution, I think what I'll have to do is store IFS='' typeset -p into an array and check each item of the array. But even this is turning out to be a bit challenging. One thing that one needs to do is look for read-only variables and then I guess turn that into a test followed by the typeset. That is typeset -p ARGC 2>/dev/null 1>/&2 && typeset -i10- r ARGC=0 Next one needs to check that the types valid which would weed out the lines above. But then we come to the typeset -ar '*' line which I guess flows onto the next line. At first I thought I could remove any lines that don't start with "typeset", but this is wrong because I could have a line like: typeset ZSH_DEBUG_CMD='if [ -d /etc/profile.d ] then for i in /etc/profile.d/*.sh do if [ -r $i ] then . $i fi done unset i fi' and all of that will read back in fine. Any suggestions? A little bit of context of why I am doing this. Recently in the zsh debugger I've added the ability to go into a nested zsh, and often one wants the existing environment of the debugged program preserved in this nested zsh. Lastly, related on a different topic. I notice there's no option for sourcing a startup file by name. Instead the closest thing is to create a temporary directory and in that create a file called .zshenv and set ZDOTDIR. This works, but strikes me as a bit awkward and more convoluted than adding an option to indicated an additional profile to run. Many POSIX-like shell languages, notably ksh don't provide such an option, bash does and it is called --init-file. And "higher-level" scripting languages which have modules like Perl, Python, or Ruby all do as well. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: typeset -p output gives shows variables which can't be read back in 2011-02-27 11:44 typeset -p output gives shows variables which can't be read back in Rocky Bernstein @ 2011-02-27 21:01 ` Bart Schaefer 2011-02-28 5:08 ` Rocky Bernstein 0 siblings, 1 reply; 8+ messages in thread From: Bart Schaefer @ 2011-02-27 21:01 UTC (permalink / raw) To: zsh-workers On Feb 27, 6:44am, Rocky Bernstein wrote: } } A little bit of context of why I am doing this. Recently in the zsh } debugger I've added the ability to go into a nested zsh, and often one } wants the existing environment of the debugged program preserved in } this nested zsh. You're kind of doomed here from the start. If the debugger is inside a shell function, for example, you're never going to get scoping back. } I would like to save to a file shell variables so that I can run a } nested zsh and then read these back in. It is becoming a bit of a } challenge because this in the output: } } typeset -i10 -r !=0 Hm, I'm a bit surprised the '!' isn't quoted there; but the real issue is that you get "not an identifier" or the like for a number of those, and "can't change type" for ones that come from zsh/parameter, plus a few "read-only variable" complaints. } typeset -ar '*' Hmm, strange. That one does NOT give "not an identifier" ... } *=() ... but that of course bombs with a globbing error. } Failing a better solution, I think what I'll have to do is store IFS='' } typeset -p into an array and check each item of the array. The zsh/parameter module $parameters hash already tells you nearly all you need to know. Something like this: () { local param type for param type in "${(kv@)parameters}" do case "$type" in (*local*) continue;; # Skip loop variables (*export*) continue;; # No need to dump/restore if exported? (*special*) continue;; # Maintained by the shell (*readonly*) continue;; (*) typeset -p "$param";; esac done } You can avoid zsh/parameter by parsing the output of "typeset +m +": () { local param type description typeset +m + | while read -A description do param="${description[-1]}" description[-1]=() if (( ${#description} )) then type="${description[*]}" else type=scalar fi case "$type" in (*local*) continue;; # Skip loop variables (*export*) continue;; # No need to dump/restore if exported? (*readonly*) continue;; (*) typeset -p "$param";; esac done } However, that doesn't let you catch "special" parameters, though you can still filter the readonly subset. Note both of these techniques still miss things like: typeset -T foo FOO I.e., there's no way to discover by examination that an array and scalar have been tied together. } But then we come to the typeset -ar '*' line which I guess flows onto the } next line. Not exactly "flows", but for arrays and associative arrays (hashes) the value can't be supplied in the typeset command, so an assignment line is needed. Also you may have to be careful with the order of assignments when you read the file back in. Some assignments to special variables (like to the "options" hash) might change shell behavior in unexpected ways. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: typeset -p output gives shows variables which can't be read back in 2011-02-27 21:01 ` Bart Schaefer @ 2011-02-28 5:08 ` Rocky Bernstein 2011-02-28 7:09 ` Bart Schaefer 0 siblings, 1 reply; 8+ messages in thread From: Rocky Bernstein @ 2011-02-28 5:08 UTC (permalink / raw) To: zsh-workers [-- Attachment #1: Type: text/plain, Size: 6094 bytes --] Thanks for the suggestions. I had been parsing typeset -p output by splitting words and using a regexp match. Now, thanks to your suggestion, I use the parameters module. As for the typeset -T and typeset -p not showing -T associations, I think that's a misfeature. What's shown now are array assignments and you don't reliably know what goes with what. Much better would be to show the association. That is if I run: typeset -T foo FOO then typeset -T should echo that among the other -T possibilities. I can always get the array and scalar values if I want. But getting the other information, as you say, is not easy if possible at all. Should I look into providing a patch for this? Saving an environment for reloading into another session, whether nested or not, might be useful in other contexts. Possibly the code you or I have in zshdb could be turned into a function and put inside the parameter module? On Sun, Feb 27, 2011 at 4:01 PM, Bart Schaefer <schaefer@brasslantern.com>wrote: > On Feb 27, 6:44am, Rocky Bernstein wrote: > } > } A little bit of context of why I am doing this. Recently in the zsh > } debugger I've added the ability to go into a nested zsh, and often one > } wants the existing environment of the debugged program preserved in > } this nested zsh. > > You're kind of doomed here from the start. If the debugger is inside > a shell function, for example, you're never going to get scoping back. > Not true in a couple of ways. First even if you changing values doesn't persist, it is useful to be able to see the values. What I'm thinking of now is adding a function save_var which takes the name of a variable one wants to persist. In an at_exit hook (or whatever the equivalent is on zsh), then those variables are written out to a file similar to what was done on entry to get all of those variables set. If there is something like a tie function like there is in Perl or a discipline function on a varaible like ksh, that might be used, but this would be on a per-variable basis. Other comments are in line below. > > } I would like to save to a file shell variables so that I can run a > } nested zsh and then read these back in. It is becoming a bit of a > } challenge because this in the output: > } > } typeset -i10 -r !=0 > > Hm, I'm a bit surprised the '!' isn't quoted there; but the real issue > is that you get "not an identifier" or the like for a number of those, > and "can't change type" for ones that come from zsh/parameter, plus a > few "read-only variable" complaints. > > } typeset -ar '*' > > Hmm, strange. That one does NOT give "not an identifier" ... > > } *=() > > ... but that of course bombs with a globbing error. > So although I can see how this might be useful as an explanation, I think it would be nice if there were some simple way (i.e. something in the typeset -p command) to filter out those things that can't be source'd back in. > > } Failing a better solution, I think what I'll have to do is store IFS='' > } typeset -p into an array and check each item of the array. > > The zsh/parameter module $parameters hash already tells you nearly all > you need to know. Something like this: > > () { > local param type > for param type in "${(kv@)parameters}" > do > case "$type" in > (*local*) continue;; # Skip loop variables > (*export*) continue;; # No need to dump/restore if exported? > (*special*) continue;; # Maintained by the shell > (*readonly*) continue;; > (*) typeset -p "$param";; > esac > done > } > > You can avoid zsh/parameter by parsing the output of "typeset +m +": > > () { > local param type description > typeset +m + | while read -A description > do > param="${description[-1]}" > description[-1]=() > if (( ${#description} )) > then type="${description[*]}" > else type=scalar > fi > case "$type" in > (*local*) continue;; # Skip loop variables > (*export*) continue;; # No need to dump/restore if exported? > (*readonly*) continue;; > (*) typeset -p "$param";; > esac > done > } > Thanks again. I have modified the code to do something like this. Note however I don't want to skip local variables, because in a debugger that's one of the important things we want to examine. And read-only variables I want to skip only if they are already set. That's why I had that typeset -p $var >/dev/null 2>&1 || prefix in the code before. (I had erroneously used && instead of || and and a stray character in there.) But all of this is easily fixed. > However, that doesn't let you catch "special" parameters, though you > can still filter the readonly subset. > > Note both of these techniques still miss things like: > > typeset -T foo FOO > > I.e., there's no way to discover by examination that an array and scalar > have been tied together. > > } But then we come to the typeset -ar '*' line which I guess flows onto the > } next line. > > Not exactly "flows", but for arrays and associative arrays (hashes) the > value can't be supplied in the typeset command, so an assignment line is > needed. > Yes, I meant that the semantic description of the variable flows into the next line, not that there was one statement split on two lines. I often write these two statements on one like with a semicolon in between. But while we are being precise, let me point out that it is wrong to say that a local variable is a "loop" variable as you suggest in the code above. > Also you may have to be careful with the order of assignments when you > read the file back in. Some assignments to special variables (like to > the "options" hash) might change shell behavior in unexpected ways. > Ok. Thanks, I will keep that in mind. Right now, I'm skipping the special variables as you had in your code. Should I need them and I discover that there is an ordering problem, I think it is a simple matter to put these in a list which gets run in list order after doing other variables first ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: typeset -p output gives shows variables which can't be read back in 2011-02-28 5:08 ` Rocky Bernstein @ 2011-02-28 7:09 ` Bart Schaefer 2011-03-01 3:09 ` Rocky Bernstein 0 siblings, 1 reply; 8+ messages in thread From: Bart Schaefer @ 2011-02-28 7:09 UTC (permalink / raw) To: zsh-workers On Feb 28, 12:08am, Rocky Bernstein wrote: } } As for the typeset -T and typeset -p not showing -T associations, I think } that's a misfeature. } } Should I look into providing a patch for this? I think first there needs to be a bit of discussion about what the result should look like. E.g. if I have typeset -T SCALAR=x:y:z array and then I do typeset -p SCALAR typeset -p array should I get the exact same output both times? Also what should the value of $parameters[foo] look like? My first idea is something like array-tied:FOO but there may be problems with that which I haven't foreseen. } Saving an environment for reloading into another session, whether } nested or not, might be useful in other contexts. Possibly the code } you or I have in zshdb could be turned into a function and put inside } the parameter module? Until you mentioned the debugger, I was completely at a loss to come up with an environment where you'd want to attempt to reload any parameter that is normally maintained by the shell internals (such as any of the variables in the $parameter module, or most of the other modules for that matter). I still can't think of one. However, parameters that are marked "typeset -H" and thus have their values suppressed in the typeset -p output can only be saved/restored by tricks that would be better applied in a C function, so I can't really argue against it. } What I'm thinking of now is adding a function save_var which takes the } name of a variable one wants to persist. That makes a bit more sense, but in that case you have a list of the names and can do for param in "${save_vars[@]}" do case $parameters[$param] in (*assoc*) print -- "typeset -A $param; $param=( ${(P@kvqq)param} )";; (*array*) print -- "typeset -a $param; $param=( ${(P@qq)param} )";; # etc. done > $the_save_file The point being that one doesn't need to dump the entire output of typeset, only the parameters whose names are explicitly known. } If there is something like a tie function like there is in Perl or a } discipline function on a varaible like ksh, that might be used, but } this would be on a per-variable basis. There's not, at this time. } On Sun, Feb 27, 2011 at 4:01 PM, Bart Schaefer <schaefer@brasslantern.com>wrote: } > } > () { } > local param type } > for param type in "${(kv@)parameters}" } > do } > case "$type" in } > (*local*) continue;; # Skip loop variables } > (*export*) continue;; # No need to dump/restore if exported? } > (*special*) continue;; # Maintained by the shell } > (*readonly*) continue;; } > (*) typeset -p "$param";; } > esac } > done } > } } } But while we are being precise, let me point out that it is wrong to } say that a local variable is a "loop" variable as you suggest in the } code above. I was referring to skipping "param" and "type", the variables for the loop over ${(kv)parameters}. There aren't any other locals in the anonymous scope (though there could be in a surrounding scope). ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: typeset -p output gives shows variables which can't be read back in 2011-02-28 7:09 ` Bart Schaefer @ 2011-03-01 3:09 ` Rocky Bernstein 2011-03-01 5:59 ` Bart Schaefer 0 siblings, 1 reply; 8+ messages in thread From: Rocky Bernstein @ 2011-03-01 3:09 UTC (permalink / raw) To: Bart Schaefer; +Cc: zsh-workers [-- Attachment #1: Type: text/plain, Size: 6152 bytes --] Comments in line. In sum, thanks again for the code suggestion. A modified version of that I now use in the debugger. On Mon, Feb 28, 2011 at 2:09 AM, Bart Schaefer <schaefer@brasslantern.com>wrote: > On Feb 28, 12:08am, Rocky Bernstein wrote: > } > } As for the typeset -T and typeset -p not showing -T associations, I think > } that's a misfeature. > } > } Should I look into providing a patch for this? > > I think first there needs to be a bit of discussion about what the result > should look like. > > E.g. if I have > > typeset -T SCALAR=x:y:z array > > and then I do > > typeset -p SCALAR > typeset -p array > > should I get the exact same output both times? > I don't understand the complexity let alone the ramifications here. If you think it worthwhile or if others may be as confused as I am please elaborate. (But I am probably not qualified to judge.) In my simple-minded way of thinking, if I had previously issued: typeset -T SCALAR=x:y:z array then "typeset -p" I would imagine would print: typeset -T SCALAR=x:y:z array what "typeset -p array" prints is another issue and dependent on the definition of "array". > Also what should the value of $parameters[foo] look like? My first idea > is something like > > array-tied:FOO > > but there may be problems with that which I haven't foreseen. > Again, you are probably in a better position than most to know about those problems. I imagine if anyone else on the list has something to add, they will. >From my standpoint, even if nothing is done here but just adding the simple-minded "typeset -p" for the tied array/scalar is an improvement. > } Saving an environment for reloading into another session, whether > } nested or not, might be useful in other contexts. Possibly the code > } you or I have in zshdb could be turned into a function and put inside > } the parameter module? > > Until you mentioned the debugger, I was completely at a loss to come up > with an environment where you'd want to attempt to reload any parameter > that is normally maintained by the shell internals (such as any of the > variables in the $parameter module, or most of the other modules for > that matter). I still can't think of one. > Alas again I am not sure I understand you here. Something I think likely is that I am inside a zsh session I've been playing around writing definitions and trying tests and setting variables and want to save out the environment so that sometime later I can come back into zsh and set things up roughly as they were before. Or perhaps in order to send back a bug report I want someone else to be able to see the relations of things. They might have to edit parts of that environment, but still the bulk of the settings would be relevant. > However, parameters that are marked "typeset -H" and thus have their > values suppressed in the typeset -p output can only be saved/restored > by tricks that would be better applied in a C function, so I can't > really argue against it. > > } What I'm thinking of now is adding a function save_var which takes the > } name of a variable one wants to persist. > > That makes a bit more sense, but in that case you have a list of the > names and can do > > for param in "${save_vars[@]}" > do case $parameters[$param] in > (*assoc*) > print -- "typeset -A $param; $param=( ${(P@kvqq)param} )";; > (*array*) > print -- "typeset -a $param; $param=( ${(P@qq)param} )";; > # etc. > done > $the_save_file > > The point being that one doesn't need to dump the entire output of > typeset, only the parameters whose names are explicitly known. > I never suggested on a *restore* everything would be saved, although now that I think of it, that would have the advantage of obviating having the user indicate which variables should persist. For now, I'll go with the more manual approach. It may in fact be that folks *don't* want changes they make to persist. Thing can always be changed later. I am kind of mixed on how much I want to use zsh-specific idioms, rather than, say using eval which may be clunkier but works on all of the POSIX shells. The more shell-specific code I have, the more maintenance I have across the 3 POSIX shell debuggers. That said, the code you have above is more shell idiomatic than the kind of thing I have been writing. I suspect there is much that could be improved in the debugger because at heart I'm not that good of a POSIX shell programmer. I hope you don't take offense, but the code you have above is a little bit wrong. We don't want to issue typeset commands because that will cause the *scope* to change. In a debugger, one is in trap function which then invoked the nested shell. The restore is done in the trap hook -- specifically in the debugger's "shell" command. But the original definition of the variable (if there is one) that a programmer typically wants to change will not be in the hook, but farther away the call chain in the debugged program. > } If there is something like a tie function like there is in Perl or a > } discipline function on a varaible like ksh, that might be used, but > } this would be on a per-variable basis. > > There's not, at this time. > > } On Sun, Feb 27, 2011 at 4:01 PM, Bart Schaefer < > schaefer@brasslantern.com>wrote: > } > > } > () { > } > local param type > } > for param type in "${(kv@)parameters}" > } > do > } > case "$type" in > } > (*local*) continue;; # Skip loop variables > } > (*export*) continue;; # No need to dump/restore if exported? > } > (*special*) continue;; # Maintained by the shell > } > (*readonly*) continue;; > } > (*) typeset -p "$param";; > } > esac > } > done > } > } > } > } But while we are being precise, let me point out that it is wrong to > } say that a local variable is a "loop" variable as you suggest in the > } code above. > > I was referring to skipping "param" and "type", the variables for the loop > over ${(kv)parameters}. There aren't any other locals in the anonymous > scope (though there could be in a surrounding scope). > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: typeset -p output gives shows variables which can't be read back in 2011-03-01 3:09 ` Rocky Bernstein @ 2011-03-01 5:59 ` Bart Schaefer 2011-03-01 6:49 ` Rocky Bernstein 0 siblings, 1 reply; 8+ messages in thread From: Bart Schaefer @ 2011-03-01 5:59 UTC (permalink / raw) To: zsh-workers On Feb 28, 10:09pm, Rocky Bernstein wrote: } } Comments in line. In sum, thanks again for the code suggestion. A } modified version of that I now use in the debugger. You're welcome; glad to help. } On Mon, Feb 28, 2011 at 2:09 AM, Bart Schaefer <schaefer@brasslantern.com>wrote: } } > E.g. if I have } > } > typeset -T SCALAR=x:y:z array } > } > and then I do } > } > typeset -p SCALAR } > typeset -p array } > } > should I get the exact same output both times? } } I don't understand the complexity let alone the ramifications here. If } you think it worthwhile or if others may be as confused as I am please } elaborate. (But I am probably not qualified to judge.) Well ... internally ... After "typeset -T SCALAR array" both SCALAR and array have the PM_TIED flag set, and each of them records the name of the other one in the ename field of the Param struct. So theoretically when one asks for the typeset form of either of them, there's enough information to emit the correct typeset -T expression. However, it's really only the scalar that stores the assignable value and the optional join character, so it takes an extra dereference to get from the name of the array to the Param for the scalar that has all the data. Upon "typeset -p array", then, the question is whether to discover the PM_TIED flag, and therefore look up the name of SCALAR and act as if "typeset -p SCALAR" had been invoked instead; or to just punt and output an assignment for the array as if it were not tied. When executing "typeset -p" with no other arguments the PM_TIED flag could be ignored for arrays because the corresponding typeset for the scalar is also going to be output. That would make the entire dump self-consistent for reloading, but would make the output for the array incomplete if taken in isolation. Which is the better course? You, I presume, would argue for the reloadable dump rather than for two assignments that are correct each alone but break when processed together. } In my simple-minded way of thinking, if I had previously issued: } typeset -T SCALAR=x:y:z array } } then "typeset -p" I would imagine would print: } typeset -T SCALAR=x:y:z array Hmm, perhaps it should output typeset -T SCALAR=x:y:z array : to make the join character explicit. Should the default be special- cased, or not? } what "typeset -p array" prints is another issue and dependent on the } definition of "array". It has to output one of two things. Either typeset -a array array=(x y z) Or typeset -T SCALAR=x:y:z array : } > Until you mentioned the debugger, I was completely at a loss to come up } > with an environment where you'd want to attempt to reload any parameter } > that is normally maintained by the shell internals (such as any of the } > variables in the $parameter module, or most of the other modules for } > that matter). I still can't think of one. } } Alas again I am not sure I understand you here. I'm drawing a distinction between parameters to which the programmer has assigned values, and parameters for which the shell has in some automated or default fashion populated the values. I can understand wanting to save and restore the former; the circumstances for the latter are harder to invent (and most of those variables are readonly besides, but not all). } Something I think likely is that I am inside a zsh session I've been } playing around writing definitions and trying tests and setting } variables and want to save out the environment so that sometime later } I can come back into zsh and set things up roughly as they were } before. } } Or perhaps in order to send back a bug report I want someone else } to be able to see the relations of things. They might have to edit } parts of that environment, but still the bulk of the settings would be } relevant. In both of those cases, though, there's a lot more that you need to save/restore than just parameters. There's a whole (lengthy) script Util/reporter in the zsh distribution just for bug report purposes. (It's been around a long time and probably needs updating.) } > for param in "${save_vars[@]}" } > do case $parameters[$param] in } > (*assoc*) } > print -- "typeset -A $param; $param=( ${(P@kvqq)param} )";; } > (*array*) } > print -- "typeset -a $param; $param=( ${(P@qq)param} )";; } > # etc. } > done > $the_save_file } > } > The point being that one doesn't need to dump the entire output of } > typeset, only the parameters whose names are explicitly known. } } I hope you don't take offense, but the code you have above is a little } bit wrong. We don't want to issue typeset commands because that will } cause the *scope* to change. No, no offense. Unfortunately there's no way re-create an associative array without issuing a "typeset -A" command first. If scope is going to be a problem, you need to figure out somehow whether what's needed is to use "typeset -gA ...". That might be a good argument for turning this into C code, where you have access to the scoping level, etc. } In a debugger, one is in trap function which then invoked the nested } shell. The restore is done in the trap hook -- specifically in the } debugger's "shell" command. But the original definition of the } variable (if there is one) that a programmer typically wants to change } will not be in the hook, but farther away the call chain in the } debugged program. Indeed, that's what I was talking about when I alluded to being "doomed from the start" a couple of messages back in the thread ... ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: typeset -p output gives shows variables which can't be read back in 2011-03-01 5:59 ` Bart Schaefer @ 2011-03-01 6:49 ` Rocky Bernstein 2011-03-01 15:15 ` Bart Schaefer 0 siblings, 1 reply; 8+ messages in thread From: Rocky Bernstein @ 2011-03-01 6:49 UTC (permalink / raw) To: zsh-workers [-- Attachment #1: Type: text/plain, Size: 7513 bytes --] Thanks for the information. The only thing I still don't understand or disagree with is the "doomed from the start comment". ksh introduced lexical scope for "function" kinds of functions, but I've not seen lexical scope in zsh. It uses dynamic scoping; dynamic scope was especially used in earlier versions of Lisp and was (is) the default for Perl. ("my" was later added in Perl.) In this kind of scope, it's sufficient to set the variable somewhere down the call chain such as in the trace hook and that persists back to outside the trace hook. I've tested this already in my nested shell example and it works as expected. But of course here you have to be careful not to run some sort of command that *defines* the variable again before the assignment or else that will now be the point of a new scope for the variable's value. So although on entry to the nested shell a definition of the type is either necessary or useful, when writing a file on exit for later source'ing it is not and is harmful: at the point in the debug hook where the values are source'd back in to pick up changed values, an associative array's value has already been defined scope-wise. If one defines a *new* variable, that is, one that was not previously defined before in the code being debugged, yes, there is no way to set that down the call chain and have that picked up above where it might be intended to be used. But in the function which saves the variables I can probably check against the original set of variables and give a warning (if this is an associative array) that this kind of save is futile. On Tue, Mar 1, 2011 at 12:59 AM, Bart Schaefer <schaefer@brasslantern.com>wrote: > On Feb 28, 10:09pm, Rocky Bernstein wrote: > } > } Comments in line. In sum, thanks again for the code suggestion. A > } modified version of that I now use in the debugger. > > You're welcome; glad to help. > > } On Mon, Feb 28, 2011 at 2:09 AM, Bart Schaefer < > schaefer@brasslantern.com>wrote: > } > } > E.g. if I have > } > > } > typeset -T SCALAR=x:y:z array > } > > } > and then I do > } > > } > typeset -p SCALAR > } > typeset -p array > } > > } > should I get the exact same output both times? > } > } I don't understand the complexity let alone the ramifications here. If > } you think it worthwhile or if others may be as confused as I am please > } elaborate. (But I am probably not qualified to judge.) > > Well ... internally ... > > After "typeset -T SCALAR array" both SCALAR and array have the PM_TIED > flag set, and each of them records the name of the other one in the > ename field of the Param struct. So theoretically when one asks for > the typeset form of either of them, there's enough information to > emit the correct typeset -T expression. However, it's really only > the scalar that stores the assignable value and the optional join > character, so it takes an extra dereference to get from the name of > the array to the Param for the scalar that has all the data. > > Upon "typeset -p array", then, the question is whether to discover > the PM_TIED flag, and therefore look up the name of SCALAR and act as > if "typeset -p SCALAR" had been invoked instead; or to just punt and > output an assignment for the array as if it were not tied. > > When executing "typeset -p" with no other arguments the PM_TIED flag > could be ignored for arrays because the corresponding typeset for the > scalar is also going to be output. That would make the entire dump > self-consistent for reloading, but would make the output for the > array incomplete if taken in isolation. Which is the better course? > > You, I presume, would argue for the reloadable dump rather than for > two assignments that are correct each alone but break when processed > together. > > } In my simple-minded way of thinking, if I had previously issued: > } typeset -T SCALAR=x:y:z array > } > } then "typeset -p" I would imagine would print: > } typeset -T SCALAR=x:y:z array > > Hmm, perhaps it should output > > typeset -T SCALAR=x:y:z array : > > to make the join character explicit. Should the default be special- > cased, or not? > > } what "typeset -p array" prints is another issue and dependent on the > } definition of "array". > > It has to output one of two things. Either > > typeset -a array > array=(x y z) > > Or > > typeset -T SCALAR=x:y:z array : > > } > Until you mentioned the debugger, I was completely at a loss to come up > } > with an environment where you'd want to attempt to reload any parameter > } > that is normally maintained by the shell internals (such as any of the > } > variables in the $parameter module, or most of the other modules for > } > that matter). I still can't think of one. > } > } Alas again I am not sure I understand you here. > > I'm drawing a distinction between parameters to which the programmer > has assigned values, and parameters for which the shell has in some > automated or default fashion populated the values. I can understand > wanting to save and restore the former; the circumstances for the latter > are harder to invent (and most of those variables are readonly besides, > but not all). > > } Something I think likely is that I am inside a zsh session I've been > } playing around writing definitions and trying tests and setting > } variables and want to save out the environment so that sometime later > } I can come back into zsh and set things up roughly as they were > } before. > } > } Or perhaps in order to send back a bug report I want someone else > } to be able to see the relations of things. They might have to edit > } parts of that environment, but still the bulk of the settings would be > } relevant. > > In both of those cases, though, there's a lot more that you need to > save/restore than just parameters. There's a whole (lengthy) script > Util/reporter in the zsh distribution just for bug report purposes. > (It's been around a long time and probably needs updating.) > > } > for param in "${save_vars[@]}" > } > do case $parameters[$param] in > } > (*assoc*) > } > print -- "typeset -A $param; $param=( ${(P@kvqq)param} )";; > } > (*array*) > } > print -- "typeset -a $param; $param=( ${(P@qq)param} )";; > } > # etc. > } > done > $the_save_file > } > > } > The point being that one doesn't need to dump the entire output of > } > typeset, only the parameters whose names are explicitly known. > } > } I hope you don't take offense, but the code you have above is a little > } bit wrong. We don't want to issue typeset commands because that will > } cause the *scope* to change. > > No, no offense. Unfortunately there's no way re-create an associative > array without issuing a "typeset -A" command first. If scope is going > to be a problem, you need to figure out somehow whether what's needed > is to use "typeset -gA ...". That might be a good argument for turning > this into C code, where you have access to the scoping level, etc. > > } In a debugger, one is in trap function which then invoked the nested > } shell. The restore is done in the trap hook -- specifically in the > } debugger's "shell" command. But the original definition of the > } variable (if there is one) that a programmer typically wants to change > } will not be in the hook, but farther away the call chain in the > } debugged program. > > Indeed, that's what I was talking about when I alluded to being "doomed > from the start" a couple of messages back in the thread ... > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: typeset -p output gives shows variables which can't be read back in 2011-03-01 6:49 ` Rocky Bernstein @ 2011-03-01 15:15 ` Bart Schaefer 0 siblings, 0 replies; 8+ messages in thread From: Bart Schaefer @ 2011-03-01 15:15 UTC (permalink / raw) To: zsh-workers On Mar 1, 1:49am, Rocky Bernstein wrote: } } Thanks for the information. The only thing I still don't understand or } disagree with is the "doomed from the start comment". You agree but don't know why? :-) E.g., if the shell you're debugging is six levels deep in function call stack at the point where you decide to break out to a new shell, the variables you dump are going to have several different dynamic scopes which it will be impossible to recreate in the new shell. It will have defined functions which the new shell won't have (though allowing $functions from zsh/parameter to be dumped and restored will get most of them). The option settings may not make sense in a top-level shell and the traps certainly won't be restored. Etc. } In [dynamic] scope, it's sufficient to set the variable somewhere down } the call chain such as in the trace hook and that persists back to } outside the trace hook. I've tested this already in my nested shell } example and it works as expected. But of course here you have to be } careful not to run some sort of command that *defines* the variable } again before the assignment or else that will now be the point of a } new scope for the variable's value. All true, but you can't simply assign to the name of an associative array variable and have it behave like an associative array. You MUST declare it first, and you can't control whether it's already been declared in some surrounding dynamic scope, so even typeset -g is not enough to assure it will persist (and if it's been declared in some surrounding scope, simple assignment will also change it in that scope and not in the global one). Hence "doomed" -- it's literally impossible to guarantee that you can store variable state in a file and then restore it again, even to replicate the state in a new shell. } So although on entry to the nested shell a definition of the type is } either necessary or useful, when writing a file on exit for later } source'ing it is not and is harmful: at the point in the debug hook } where the values are source'd back in to pick up changed values, an } associative array's value has already been defined scope-wise. I'm not sure how you assure the truth of that last statement, but you must be working in a more constrained context than I'm imagining. ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2011-03-01 15:15 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2011-02-27 11:44 typeset -p output gives shows variables which can't be read back in Rocky Bernstein 2011-02-27 21:01 ` Bart Schaefer 2011-02-28 5:08 ` Rocky Bernstein 2011-02-28 7:09 ` Bart Schaefer 2011-03-01 3:09 ` Rocky Bernstein 2011-03-01 5:59 ` Bart Schaefer 2011-03-01 6:49 ` Rocky Bernstein 2011-03-01 15:15 ` Bart Schaefer
Code repositories for project(s) associated with this public inbox https://git.vuxu.org/mirror/zsh/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).