ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Bad coders make a mess out of the most structured language elements. Deeply nested loops and if statements can become nicely wound spaghetti, but still spaghetti.
Goto's certainly serve a purpose... if used with care.
Ever tried to write a function which has to be left immediately in multiple conditions, but with the execution of some statements, like closing a file or releasing a mutex? Without goto?
Well, Linus doesn't seem to agree entirely with you.
Goto is always considered bad style these days, when we have safer constructs like while, for, if-else, etc.
The problem is with the compiler or interpreter that generates code out of these constructs... they tend to generate too much redundant code. While GOTOs are considered fine at the assembly level, they are not encouraged when using higher-level languages...and these include shell scripts!! Shell interpreters are written in a higher-level language anyway...
If you think bash or csh (or other shells) aren't good enough for you, write another one that compiles (or interpretes) while-, or for-loop constructs that generates the least assembly (or binary) code.
This is probably the best way of using GOTOs, by writing a compiler (or assembler, interpreter, etc.) in assembly. There's a super elegant solution of using JMPs for 80x86.
Well, Linus doesn't seem to agree entirely with you.
I have a problem.
I have built a script which goes through many 'if' tests. About twenty of them. Some of them, about 12, exit, if they meet certain conditions.
The problem is that if the script just exits, it leaves the system in bad condition: devices mounted to wrong directories etc.
The script should run about ten lines of code while exiting.
How to do this without GOTO ?
In good old days before purist programmers condemned it, we used GOTO to make this easy in Basic and Fortran.
Use a 'trap' to run a cleanup routine before exiting:
Code:
## User cancelled at a 'sensitive' spot, so scold them!
trap_int() {
echo
echo $RED"*** OUCH!!! ***"$NORMAL
emergency_restore
exit
}
# emergency_restore
emergency_restore() {
echo "Please don't interrupt during installation!"
# do whatever fixups (unmounts, etc) here:
}
# set a trap like this in your code before running 'sensitive' code:
trap trap_int 2
# The above just traps -INT, but you can specify multiple signals to trap
As far as I know, you can't 'revoke' a trap, so if you only need it at certain places and not in others, you can use another 'dummy' trap which does nothing in order to cancel the one above.
Use a 'trap' to run a cleanup routine before exiting:...
Thank you. This 'trap' didn't help this time, but it cave me an idea.
Now I'm using a function 'quit', where I can write all the cleanup I need.
Using one variable to tell, if the calling test has gone err or is the system exiting normally.
The whole script is too large to be copied here, I'll publish it on my site, when it is more mature. Here is small pieces of it to show how:
This script calls the main script:
Code:
#-- Calling script--
MAKER=/home/bin/backup/make_snapshot.sh;
# Call the main script:
$MAKER;
if (( $? )); then {
$ECHO "make_snapshot.sh script has been run" >>$ERROR_FILE;
$CAT $ERROR_FILE | $SENDMAIL $RECEIVER;
} fi;
This script makes most of the work:
Code:
#--Piece from the beginning of the script--
#------- VARIABLES -----------
# Set ERR=1 for default:
ERR=1;
#------- FUNCTIONS -----------
function quit {
$UMOUNT $MOUNT_DEVICE;
if (( $? )); then {
$ECHO "(1) ERROR: UNmounting $SNAPSHOT_RW" >>$ERROR_FILE;;
# ERR=1; Not needed, default
} fi;
exit $ERR;
}
#------- The MILL ----------
# make sure we're running as root
if (( `$ID -u` != 0 )); then {
$ECHO "(2) ERROR: Must be root. Exiting." >>$ERROR_FILE;;
# ERR=1; Not needed, default
quit;
} fi;
# ERR is '1' by default, change it to '0' when everything is OK:
ERR=0; quit;
# That's all, folks !
Some might wonder, why the scripts live in /home/bin/Backup rather than /usr/bin or some 'normal' directory.
This is because I have a habit to have three HD:s in my servers: one for the system, another for the /home and the third, the largest for the /BACKUP. I move /root, /var/www to /home and so it is MUCH easier to update system, make backups and recover broken systems. It is enough to backup /home and /etc.
It is very near I could make the whole system disk RO.
Let's say you have a function which initialized a few pointers, but those are only needed in that function.
You have to return from the function in let's say 20 if statement.
You have 3 choices:
- Free the pointers in every statement before return. This is BAD. If you add a new pointer, you have to write 20 new line!
- Write a function that will be called by this function. Still not too good. Our code will be fulled with "func1_quit", "func2_quit", etc unneeded functions, which just makes it more unreadable and robust. (You are trying to understand a function, every time you see the ..._quit called, you have to find it in the code, then go back to our function)
- Write a goto that will jump to the end of the function where all the needed destruction statements are there+you will have only 1 return. This way the code will be the MOST readable of every cases. That's why the linux kernel developers are using this method.
The teachers are saying "Don't use goto" just to learn the procedural thinking well, because goto is just extends this practise, and doesn't replace it!
The evolution of a programmer in terms of goto looks like:
-Using goto a lot of places (where he shouldn't)->BAD
-He learnt the goto is bad, won't use it anymore->Better, but still far from professional
-He realizes that goto can be good too, and using it where it makes the code more readable and easily maintenable->It's a good start..
I am converting JCL to shell script (for a client) and need to simulate the IBM JCL RESTART command. I learnt to program in COBOL and PL/1 over 20 years ago and agree that using goto to create spaghetti is bad but goto can be a lifesaver too when used judiciously.
Yeah, me too. What about using REXX or ooREXX for your client then - AFAIR there exist labels and the SIGNAL instruction. There are free implementations of it for Linux.
Like I said in one of the posts above, I worked out a way to have restart steps. I did this in 2006/2007 and it all worked sweetly, like a charm, I even simulated GDGs is Korn shell with the ability to roll back and do batch reruns. I have already forgotten most of the details and moved on to newer adventures. Let me know if you have questions and I can try to help.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.