HP OpenVMS Systems Documentation

Content starts here

HP BASIC for OpenVMS
User Manual


Previous Contents Index

10.1.5 Date and Time Functions

HP BASIC supplies functions to return the date and time in numeric or string format. The following sections discuss these functions.

Note that you can also use certain system services and Run-Time Library routines for more sophisticated date and time functions. See the HP OpenVMS System Services Reference Manual and the VMS Run-Time Library Routines Volume for more information.

10.1.5.1 DATE$ Function

The DATE$ function returns a string containing a day, month, and year in the form dd-Mmm-yy. The date integer argument to the DATE$ function can have up to six digits in the form yyyddd, where yyy specifies the number of years since 1970 and ddd specifies the day of that year. If the numeric expression is zero, DATE$ returns the current date.


PRINT DATE$(0)
PRINT DATE$(126)
PRINT DATE$(6168)
END

Output


15-Jun-85
06-May-70
16-Jun-76

If you supply an invalid date (for example, day 370 of the year 1973), the results are undefined.

See Section 10.1.5.2 for the recommended replacement for DATE$, which has a two-digit year field in the result string.

10.1.5.2 DATE4$ Function

The DATE4$ function is strongly recommended as replacement for the DATE$ function to avoid problems in the year 2000 and beyond. It functions the same as the DATE$ function except that the year portion of the result string contains two more digits indicating the century. For example:


PRINT 32150, DATE$ (32150), DATE4$ (32150)

Produces the following output:


32150   30-May-02   30-May-2002

See the description of the DATE$ function for more information.

10.1.5.3 TIME$ Function

The TIME$ function returns a string displaying the time of day in the form hh:mm AM or hh:mm PM. TIME$ returns the time of day at a specified number of minutes before midnight. If you specify zero in the numeric expression, TIME$ returns the current time of day. For example:


PRINT TIME$(0)
PRINT TIME$(1)
PRINT TIME$(1440)
PRINT TIME$(721)
END

Output


03:53 PM
11:59 PM
12:00 AM
11:59 AM

10.1.5.4 TIME Function

The TIME function requests time and usage information from the operating system and returns it to your program. The information returned by the TIME function depends on the value of the argument passed to it. The values and the information they return are as follows:

Value Information Returned
0 Returns the number of seconds elapsed since midnight
1 Returns the current job's CPU time in tenths of a second
2 Returns the current job's connect time in minutes
3 Returns zero
4 Returns zero

All other arguments to TIME are undefined and cause HP BASIC to signal "Not implemented" (ERR=250).

10.1.6 Terminal Control Functions

HP BASIC provides several terminal control functions. These functions let you:

  • Enable and disable Ctrl/C trapping
  • Enable and disable terminal echoing
  • Read a single keystroke from a terminal

10.1.6.1 CTRLC and RCTRLC Functions

The CTRLC function enables Ctrl/C trapping, and the RCTRLC function disables Ctrl/C trapping. When Ctrl/C trapping is enabled, control is transferred to the program's error handler when Ctrl/C is detected at the controlling terminal.

Ctrl/C trapping is asynchronous. The trap can occur in the middle of an executing statement, and a statement so interrupted leaves variables in an undefined state. For example, the statement A$ = "ABC", if interrupted by Ctrl/C, could leave the variable A$ partially set to "ABC" and partially left with its previous contents.

For example, if you type Ctrl/C to the following program when Ctrl/C trapping is enabled, an "ABORT" message prints to the file open on channel #1. This lets you know that the program did not end correctly.


WHEN ERROR USE error_handler
      Y% = CTRLC
   .
   .
   .
END WHEN
HANDLER error_handler
      IF ERR = 28 THEN PRINT #1%, "Abort"
   .
   .
   .
END HANDLER

Note

When you trap Ctrl/C with an error handler, your program might be in an inconsistent state; therefore, you should handle the Ctrl/C error and exit the program as quickly as possible.

10.1.6.2 ECHO and NOECHO Functions

The NOECHO function disables echoing on a specified channel. Echoing is the process by which characters typed at the terminal keyboard appear on the screen.

If you specify channel #0 (your terminal) as the argument, the characters typed on the keyboard are still accepted as input; however, they do not appear on the screen.

The ECHO function enables echoing on a specified channel and cancels the effect of the NOECHO function on that channel.

If you do not use these functions, ECHO is the default. The following program shows a password routine in which the password does not echo:


Y% = NOECHO(0%)
INPUT "PASSWORD"; pword$
IF pword$=="PLUGH" THEN PRINT "THAT IS CORRECT"
END IF
Y% = ECHO(0%)
END

Note that the Y% = ECHO(0%) statement is necessary to turn the echo back on. If this statement were not included, then all subsequent user inputs would not echo to the terminal screen.

10.1.6.3 INKEY$ Function

The INKEY$ function reads a single keystroke from a terminal opened on a specified channel and returns the typed character.

If you specify a channel that is not open, HP BASIC signals the error "I/O channel not open" (ERR=9). If a file or a device other than a terminal is open on the channel, HP BASIC signals the error "Illegal operation" (ERR=141).

Once you have specified a channel, HP BASIC allows you to specify an optional WAIT clause. A WAIT clause followed by no value tells HP BASIC to wait indefinitely for input to become available. A WAIT clause followed by a value from 1 to 255 tells HP BASIC to wait the specified number of seconds for input.


DECLARE STRING
KEYSTROKE Inkey_Loop: WHILE 1%       KEYSTROKE = INKEY$(1%,WAIT)

      SELECT KEYSTROKE
          CASE '26'C
               PRINT "Ctrl/Z to exit"
               EXIT Inkey_Loop
          CASE CR,LF,VT,FF,ESC
               PRINT "Line terminator"
          CASE "PF1" TO "PF4"
               PRINT "P key"
          CASE "E1" TO "E6"
               PRINT "VT200 Function key"
          CASE "KP0" TO "KP9"
               PRINT "Application keypad key"
          CASE < SP
               PRINT "Control character"
          CASE '127'C
               PRINT "<DEL>"
          CASE ELSE
               PRINT "Character is "; KEYSTROKE
       END SELECT
NEXT

10.2 User-Defined Functions

The DEF statement lets you create your own single-line or multiline functions.

In HP BASIC, a function name consists of the following:

  • The letters FN
  • From 1 to 28 letters, digits, underscores, or periods
  • An optional percent sign or dollar sign

Integer function names must end with a percent sign (%), and string function names must end with a dollar sign ($); therefore, the function name can have up to 31 characters. If the function name ends with neither a percent sign nor a dollar sign, the function returns a real number.

You can create user-defined functions using these function naming rules; however, it is recommended that you use explicit data typing when defining functions for new program development. See Chapter 12 for an example of an explicitly declared function. Note that the function name must start with FN only if the function is not explicitly declared, and a function reference lexically precedes the function definition.

DEF functions can be either single-line or multiline. Whether you use the single-line or multiline format for function definitions depends on the complexity of the function you create. In general, multiline DEF functions perform more complex functions than single-line DEF functions and are suitable for recursive operations.

If you want to pass values to a function, the function definition requires a formal parameter list. These formal parameters are the variables used to calculate the value returned by the function. When you invoke a function, you supply an actual parameter list; the values in the actual parameter list are copied into the formal parameter at this time. DEF functions allow up to 255 formal parameters. You can specify variables, constants, or array elements as formal parameters, but you cannot specify an entire array as a parameter to a DEF function.

10.2.1 Single-Line DEF Functions

In a single-line DEF, the function name, the formal parameter list, and the defining expression all appear on the same line. The defining expression specifies the calculations that the function performs. You can pass up to 255 arguments to this function through the formal parameter list. These parameters are variables local to the function definition, and each formal parameter can be preceded by a data type keyword.

The following example creates a function named fnratio. This function has two formal parameters: numer and denomin, whose ratio is returned as a REAL value.

When the function is invoked, HP BASIC does the following:

  • Copies the values 5.6 and 7.8 into the formal parameters numer and denomin
  • Evaluates the expression to the right of the equal sign
  • Returns the value to the statement that invoked the function (the PRINT statement)

The PRINT statement then prints the returned value.


DEF REAL fnratio (numer, denomin) = numer / denomin
PRINT fnratio(5.6, 7.8)
END

Output


 .717949

Note that the actual parameters you supply must agree in number and data type with those in the formal parameter list; you must supply numeric values for numeric variables, and string values for string variables.

The defining expression for a single-line function definition can contain any constant, variable, HP BASIC built-in function, or any user-defined function except the function being defined. The following examples are valid function definitions:


DEF FN_A(X) = X^2 + 3 * X + 4
DEF FN_B(X) = FN_A(X) / 2 + FN_A(X)
DEF FN_C(X) = SQR(X+4) + 1
DEF CUBE(X) = X ^ 3

Note that the name of the last function defined does not begin with FN. This is valid as long as no reference to the function lexically precedes the function definition.

You can also define a function that has no formal parameters. The following function definition uses three HP BASIC built-in functions to return an integer corresponding to the day of the month:

  • DATE$(0) returns a date string in the form dd-Mmm-yy.
  • The SEG$ function strips out of this value the characters starting at character position 1 up to and including the character at position 2 (the day number).
  • The VAL% function converts this resulting numeric string to an integer. In this way, fnday_number returns the day of the month as an integer.


DEF INTEGER fnday_number = VAL% (SEG$(DATE$(0%), 1%, 2%))

10.2.2 Multiline DEF Functions

The DEF statement can also define multiline functions. Multiline DEF functions are useful for expressing complicated functions. Note that multiline DEF functions do not have the equal sign and defining expression on the first line. Instead, this expression appears in the function block, assigned to the function name.

Note

If a multiline DEF function contains DATA statements, they are global to the program unit.

Multiline function definitions can contain any constant, variable, HP BASIC built-in function, or user-defined function. In HP BASIC, the function definition can contain a reference to the function you are defining. Therefore, a multiline DEF function can be recursive, or invoke itself; however, HP BASIC does not detect infinitely recursive DEF functions during compilation. If your program invokes an infinitely recursive DEF function, HP BASIC will eventually signal a fatal run-time error, typically the error "Access violation."

You can use either the END DEF or EXIT DEF statements to exit from a user-defined function. The EXIT DEF statement is equivalent to an unconditional transfer to the END DEF statement.

The following example shows a multiline DEF function that uses both the EXIT and END DEF statements. The defining expression of the function is in the ELSE clause. This assigns a value to the function if A is less than 10. The second set of output shows what happens when A is greater than 10; HP BASIC prints "OUT OF RANGE" and executes the EXIT DEF statement. The function returns zero because control is transferred to the END DEF statement before a value was assigned. In this way, this example tests the arguments before the function is evaluated.


DEF fn_discount(A)
    IF A > 10
    THEN
       PRINT "OUT OF RANGE"
       EXIT DEF
    ELSE
       fn_discount = A^A
    END IF
END DEF

INPUT Z
PRINT fn_discount(Z)
END

Output 1


? 4
 256

Output 2


? 12
OUT OF RANGE
 0

If you do not explicitly declare the function with the DECLARE statement, the restrictions for naming a multiline DEF function are the same as those for the single-line DEF function; however, explicitly declaring a DEF function can make a program easier to read and understand. For instance, Example 1 concatenates two strings and Example 2 returns a number in a specified modulus.


DECLARE STRING FUNCTION concat (STRING, STRING) !Declare the function
   .
   .
   .
DEF STRING concat (STRING Y, STRING Z)
concat = Y + Z  !Define the function
FNEND
   .
   .
   .
new_string$ = concat(A$, B$) !Invoke the function
   .
   .
   .
END


DECLARE REAL FUNCTION mdlo (REAL, INTEGER)
DEF mdlo( REAL  argument, INTEGER modulus )
  !Check for argument equal to zero

  EXIT DEF IF argument = 0
  !Check for modulus equal to zero, modulus equal to absolute
  !value of argument, and modulus greater than absolute
  !value of argument.

  SELECT modulus
  CASE = 0%
      EXIT DEF
  CASE > ABS( argument )
      EXIT DEF
  CASE = ABS( argument )
      mdlo = argument
      EXIT DEF
  END SELECT

  !If argument is negative, set flag negative% and set argument
  !to its absolute value.
  IF argument < 0
     THEN argument = ABS( argument )
        negative%  = -1%
  END IF
  UNTIL argument < modulus
        argument = argument - modulus

        !If this calculation ever results in zero, mdlo returns zero
        IF argument = modulus
           THEN mdlo = 0
           EXIT DEF
        END IF
  NEXT

  !Argument now contains the right number, but the sign might be wrong.
  !If the negative argument flag was set, make the result negative.

  IF negative%
     THEN mdlo = - argument
     ELSE mdlo = argument
  END IF

END DEF

INPUT "PLEASE INPUT THE VALUE AND THE MODULUS"; X,Y
PRINT mdlo(X,Y)
END

Output


PLEASE INPUT THE VALUE AND THE MODULUS? 7, 5
 2

Because these functions are declared in DECLARE statements, the function names do not have to conform to the traditional HP BASIC rules for naming functions.

Recursion occurs when a function calls itself. The following example defines a recursive function that returns a number's factorial value:


DECLARE INTEGER FUNCTION factor ( INTEGER )
DEF INTEGER factor ( INTEGER F )
   IF F <= 0%
      THEN factor = 1%
      ELSE factor = factor(F - 1%) * F
   END IF
END DEF
INPUT "INPUT N TO FIND N FACTORIAL"; N%
PRINT "N! IS"; factor(N%)
END

Output


INPUT N TO FIND N FACTORIAL? 5
N! IS 120

Any variable accessed or declared in the DEF function and not in the formal parameter list is global to the program unit. When HP BASIC evaluates the user-defined function, these global variables contain the values last assigned to them in the surrounding program module.

To prevent confusion, variables declared in the formal parameter list should not appear elsewhere in the program. Note that if your function definition actually uses global variables, these variables cannot appear in the formal parameter list.

You cannot transfer control into a multiline DEF function except by invoking it. You should not transfer control out of a DEF function except by way of an EXIT DEF or END DEF statement. This means that:

  • If the DEF function contains an ON ERROR GOTO, GOTO, ON GOTO, GOSUB, ON GOSUB, or RESUME statement, that statement's target line number must also be in that DEF function.
  • An ON ERROR GO BACK statement can transfer control out of a DEF function; however, a RESUME statement in an error handler outside the DEF function cannot transfer control back into the DEF function.
  • If the DEF function contains a handler, and was invoked from a protected region, an EXIT HANDLER statement causes control to be transferred to the specified handler for that protected region. However, if the DEF function contains a handler but was not invoked from a protected region, an EXIT HANDLER statement causes control to be transferred to the default error handler.
  • A subroutine cannot be shared by more than one DEF function; however, if you rewrite the subroutine as a DEF function with no parameters, other function definitions can share it.

A DEF function never changes the value of a parameter passed to it. Also, because formal parameters are local to the function definition, you cannot access the values of these variables from outside the DEF statement. These variable names are known only inside the DEF statement.

In the following example, the variable first is declared only in the function fn_sum. When HP BASIC sees the second PRINT statement, it assumes that first is a new variable that is not declared in the main program. If you try to run this example, HP BASIC signals the error "Explicit declaration of first required." If you do not specify the OPTION TYPE = EXPLICIT statement, HP BASIC assumes that first is a new variable and initializes it to zero.


OPTION TYPE = EXPLICIT
DECLARE INTEGER A, B
DEF fn_sum(INTEGER first, INTEGER second) = first + second
A = 50
B = 25
PRINT fn_sum(A, B)
PRINT first
END


Previous Next Contents Index