LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Why do scripting languages use a reverse convention for indicating TRUE and FALSE? (https://www.linuxquestions.org/questions/programming-9/why-do-scripting-languages-use-a-reverse-convention-for-indicating-true-and-false-4175661191/)

hazel 09-20-2019 03:13 AM

Why do scripting languages use a reverse convention for indicating TRUE and FALSE?
 
In C, numerals have a boolean significance. Zero is FALSE as are its equivalents: the NULL pointer and the NULL character. Non-zero numbers are TRUE; in practice TRUE=1. This is clearly intuitive. Computers work in binary: 1 and 0, on and off, set and unset, pulse or no pulse. It seems logical that if there is no pulse when a pulse was expected, that signifies FALSE.

But when calling exit() in your program, you pass 0 for success and 1 for error or failure. That's because a script may need to analyse the behaviour of your program and all Unix scripting languages use that convention rather than the more intuitive one. I assume there must be some historical reason for that. Does anyone know how it originated?

NevemTeve 09-20-2019 03:26 AM

> But when calling exit() in your program, you pass 0 for success and 1 for error or failure.

Well, these aren't logical values, they are status-codes: 0 means success, other values are error codes. As many different errors may happen, it is quite plausible. (Edit: IBM /360 mainframe's programs often used these values: 0=OK, 4=Warning, 8=Error, 12+=FatalError)

(I think it would be easier if program '/bin/true' would called 'success' and '/bin/false' would be 'fail'.)

ehartman 09-20-2019 04:23 AM

Quote:

Originally Posted by hazel (Post 6038491)
But when calling exit() in your program, you pass 0 for success and 1 for error or failure.

No, you pass an error code (int), not a boolean:
Code:

void _exit(int status);
    The value status & 0377 is returned to the parent process as the process's
    exit status, and can be collected using one of the wait(2) family of calls.

(from the man page of the system call _exit(2))
So the error code is limited to the range 0(=successfull exit) thru 0377 octal (255 decimal), so is in fact an UNsigned byte.
As the shell used does the "wait" call, it will get this 0 to 255 exit value from the application and that value is what the scripts are testing for.

hazel 09-20-2019 05:26 AM

So "0" means "No errors". Yes, that would make sense. I think what confused me is that conditional structures in scripts (for example if...elif...else...fi in bash) treat the exit codes of programs in a boolean way and you can do boolean operations on them. They behave like TRUE and FALSE.

freemedia2018 09-20-2019 05:28 AM

You can think of it as a boolean flag IS_ERROR

0 = FALSE | nonzero = TRUE

It makes sense to have IS_ERROR rather than IS_SUCCESSFUL because you dont need to be specific about "there is no error".

So 0 is the only FALSE but nonzero lets you be specific about things that can go into more detail (which nonzero) ... also

C isnt different, so this isnt about scripting languages: https://en.wikipedia.org/wiki/Exit_status#C_language

rtmistler 09-20-2019 05:58 AM

I suggest that one be extremely cautious assuming just values of 1 and 0. Some commands return other than just those two values. Yes a non-zero value means a problem, however it usually is beneficial to understand the difference between one error and another.

Firerat 09-20-2019 06:09 AM

what everyone else says...

0 = nothing to report
1 = bust
2 = bust with more detail
...
404 = the page you are looking for does not exist


and you can pass error codes
Code:

#!/bin/bash
errorme() {
return $1
}
report() {
case $1 in
    0) echo "something went very very wrong"
        ;;
    1) echo "yeah, it broke";;
    2) echo "ok, so it is the thingy";;
    3) echo "the thingy + the watsit";;
    4) echo "bash did it";;
    *) echo "unknown error"
      printf "\t%02d\t" ${count}
        return 3;;
esac
return 0
}
count=0
for i in {0..5} {5..0}
do
    ((count++))
    printf "%02d\t" ${count}
    if (errorme $i )
    then
        echo ok
    else
        report $? || report $?
    fi
done


bigearsbilly 09-20-2019 06:15 AM

It's because you are returning a useful value on error to the caller. All processes, not just shell scripts return a value, 0 means OK.

It's actually a combination of things, including if the process was killed etc,

https://linux.die.net/man/2/waitpid

https://en.wikipedia.org/wiki/Exit_status

ehartman 09-20-2019 06:22 AM

Quote:

Originally Posted by hazel (Post 6038534)
So "0" means "No errors". Yes, that would make sense.

For instance in a program of mine (for freedb CD info database) I use
Code:

perror("Open error");
 return(1);

 perror("Stat error");
 return(2);

and at the end  return(0);

The C standard specifies two constants, EXIT_SUCCESS and EXIT_FAILURE, that may be passed to exit() to indicate successful or unsuccessful termination, respectively.
(and, of course, these have as value 0 resp 1).

Quote:

I think what confused me is that conditional structures in scripts (for example if...elif...else...fi in bash) treat the exit codes of programs in a boolean way and you can do boolean operations on them. They behave like TRUE and FALSE.
Yeah, but bash uses TWO different constructions for exit codes then for logical expressions:
Code:

    if <commandline>
tests for the exit status OF the command, so 0 means OK, no errors
  if [ <logical expression> ]
(note the []) tests a logical expression for TRUE or FALSE


ntubski 09-20-2019 07:48 AM

Quote:

Originally Posted by ehartman (Post 6038554)
Yeah, but bash uses TWO different constructions for exit codes then for logical expressions:
Code:

    if <commandline>
tests for the exit status OF the command, so 0 means OK, no errors
  if [ <logical expression> ]
(note the []) tests a logical expression for TRUE or FALSE


I find it more useful to think of bash as only having the first construct for exit codes, and [ <logical expression> ] is simply a particular example of <commandline>.

hazel 09-20-2019 08:15 AM

Quote:

Originally Posted by ntubski (Post 6038593)
I find it more useful to think of bash as only having the first construct for exit codes, and [ <logical expression> ] is simply a particular example of <commandline>.

Well, that's the point I was making. Bash treats exit codes as booleans. Though as far as I can remember, the [ <logical expression> ] construct is actually "test(logical expression)" where test is the old Bourne shell test command. Bash symlinks "[" to "test". That's why you have to have a space after it.

I remember reading in some programming guide or other that it's bad practice to have multiple error codes for different kinds of errors because nobody wants to have to look them up. The obvious exception is grep, where failure to find a string isn't really an error at all if the string isn't there. So grep has 0 for finding the string, 1 for not finding it and 2 for genuine errors such as bad syntax in search string.

ehartman 09-20-2019 08:21 AM

Quote:

Originally Posted by hazel (Post 6038602)
where test is the old Bourne shell test command.

Which even exists as its own external command (see "man test").
So "if [ ..." can be written too as "test ...", which I often use as a one-line if:
Code:

test -d $BASEDIR || mkdir $BASEDIR
or even
test $? -eq 0 && rm -f $SOURCE || echo "Error in convertion of $SOURCE"


hazel 09-20-2019 08:28 AM

OK. "&&" and "||" are boolean operators, aren't they? So how does that work if the exit codes from test and rm are just integers?

Firerat 09-20-2019 08:29 AM

read

https://mywiki.wooledge.org/BashGuid...ndConditionals


but the quick answer is, you use case
I wonder if I can find an example?

here is one I made earlier
https://www.linuxquestions.org/quest...1/#post6038551

ehartman 09-20-2019 08:43 AM

Quote:

Originally Posted by hazel (Post 6038609)
OK. "&&" and "||" are boolean operators, aren't they?

Yes, but they work on EXIT-codes, so for them 0 means success and anything else means failure (of the previous command).


All times are GMT -5. The time now is 09:15 AM.