Application Development |
JPL is an interpreted language with a C-like syntax. Because you can write and edit JPL code within the editor, you can write and execute procedures without interrupting your development work flow. You can also write JPL procedures directly to a library and call them via event-type properties provided in the Properties window for screens and widgets. Use JPL for rapid prototyping and later rewrite the procedures in C. Or leave the code unchanged; JPL can get most jobs done quickly and efficiently.
JPL Modules and Procedures |
JPL modules contain one or more procedures written in JPL. You create modules through Panther's own JPL editor (described under "Writing JPL in the Editor") or in a text editor. Screen modules are created through the FocusJPL Procedures property; widget modules through the ValidationJPL Validation property; and report modules through the InclusionsJPL Procedures property. Widget, screen and report JPL modules are saved in the screen binaries; Panther automatically reads these at the appropriate stage of program execution. You can also create library modules directly in the editor workspace. For faster access, you can install library modules in the application's memory-resident list.
A module contains one or more procedures. The first procedure of a module can be unnamed. All subsequent procedures are named through JPL's proc command. For example, the following module has two procedures; the first is unnamed, the second named warning
:
if actual_cost > forecast_cost
call warning()
proc warning()
msg emsg "Value exceeds budget forecast."
Unnamed and named procedures are different in two ways:
Refer to Figure 19-1 to view a sample JPL module.
The proc For example, the earlier If a procedure is called as an event function for a widget or screen—for example, as a screen's exit function—and the function name omits parentheses, Panther automatically passes standard arguments to the procedure. These arguments indicate the current status of the widget or screen. Their number and type vary; for example, two arguments are passed for screens, four for widgets, and three for grid widgets. The procedure's proc statement must contain the appropriate number of parameters in order to receive these arguments.
For example, you might define the following procedure in a screen's JPL module in order to handle grid data:
You can set
Note:
Precedence is always given to arguments that are specified in the property string. For example, if a grid widget's Entry Function property contains the string The unnamed procedure of the module for a screen or widget module is always supplied standard arguments that indicate the current status of the screen or widget. To receive these arguments, the unnamed procedure must have a parms statement.
For more information about the standard arguments available for screens and widgets, refer to "Calls from Screens and Widgets." The parms command description shows how to declare parameters in an unnamed procedure.
An unqualified proc command returns an integer value. You can specify to return a string or double precision value by qualifying the Procedure execution begins with the first statement of the procedure and continues to the end of the procedure, or until a return statement executes. If an execution error occurs, Panther aborts execution of the current procedure, posts an error message, and returns to the procedure's caller. In all cases, a procedure returns to its caller when execution ends.
Panther interprets each physical line as a separate statement, unless the line ends with the backslash ( By default, Panther executes JPL procedures sequentially from start to finish. You can use JPL's if, Conditional and loop statements ( The following example shows an if statement that contains a block of two statements:
A left and right brace on the same line indicate a null statement. In the following example, the Panther procedures (including the unnamed procedure) can contain include statements that specify a JPL library module. At runtime, Panther compiles and inserts this module within the calling procedure before execution begins.
Include statements have the following syntax:
where Panther looks for Parameters
command can specify parameters that receive arguments passed by the procedure's caller. You specify parameters as a comma-delimited argument list within parentheses. The procedure's caller can pass in constants, global constants, variables, or colon-expanded variables as arguments. Panther passes arguments by value—that is, the called procedure gets its own private copies of the values in the calling procedure's arguments. This means that the called procedure cannot directly alter variables in its caller; it can only alter its own copies.
warning
procedure is modified below; it now expects its caller to supply two arguments that are copied to actual
and forecast
. A more informative message is produced by using the colon-expanded values of these variables:
if actual_cost > forecast_cost
call warning(actual_cost, forecast_cost)
proc warning (actual, forecast)
vars diff = actual - forecast
msg emsg "Value in :actual exceeds budget forecast by $:diff" Passing Standard Arguments to JPL Procedures
proc gridProc( basefld, occ_no, status
)
gridProc
in any of several grid properties. When Panther calls this procedure at runtime, it sets parameters basefld
, occ_no
and status
with the three standard arguments associated with grids. So, if a grid's Row Entry Function (row_entry_func
) property contains the string gridProc
, Panther calls the procedure each time the cursor enters a new row and sets its three parameters to the grid's base widget number, the number of the current occurrence, and an integer bitmask that describes why the procedure was called.
gridEntry(val)
, Panther supplies the contents of val
to procedure gridEntry
. If arguments are explicitly omitted through empty parentheses (), Panther does not supply the standard arguments.
Return Types
proc
command with the keywords string
or double
, respectively. For example, the following sequence of statements passes data from variables data1
and data2
to procedure process_input
, which is defined to return a double precision value. This return value is used to determine whether the if
statement evaluates to true or false:
if process_input(data1, data2) > 0.16667
...
double proc process_input(d1, d2)
vars retval
//process d1 and d2 values
return retval Procedure Execution
\
) continuation character. JPL physical lines can be up to 253 characters in length.
Control Flow Statements
else
, for, while, switch, case
, default
, break, and next statements to manipulate the order of statement execution. JPL has no limit to how many levels deep you can nest control flow statements.
if
, else
, for
, while
, switch
) allow curly braces { }
as blocking characters so you can conditionally execute multiple statements. Each blocking character must have its own line except to specify a null statement—{}
. If you nest multiple blocks, make sure that all block characters are paired correctly.
if cost > 1000
{
exceptions = exceptions + 1
msg emsg "The cost is very great."
}for
statement keeps count while testing a condition. Because no other statements are required, the for
block consists of a null statement:
for i = 1 while str(i, 1) != " "
{ } Included Modules
include
module
module
is any JPL library module. The included module can also contain its own include
statements. You can nest up to eight include statements.
module
in this order:
You can enter commented text in JPL in three ways:
//
) characters. JPL treats all remaining text on that line as a comment.
Note:
You cannot embed comments within a line of code; all text on a line that follows a comment character, including */
, is ignored at runtime.
#
) character. JPL treats the entire line as a comment.
Sample JPL Module
Figure 19-1 This sample screen-level JPL module makes a JPL module public and displays additional options for front desk employees.
Module Types |
Panther lets you create the following types of JPL modules:
An application's ability to access the procedures in a JPL module depends on its type and how it is loaded and called. For instance, Panther executes a widget module only during widget validation. The procedures in this module can only be called by each other and are invisible to the rest of the program. Conversely, named procedures in screen modules are available to the entire application while the screen is active.
Panther's ability to access library and memory-resident modules depends on how they are loaded and called. If you load a module into memory as a public module, its named procedures are visible to the entire application and can be called directly. If a module is not public, the library in which it resides must be open and the module can only be called by its filename; this invokes the module's unnamed procedure. The named procedures in this module are accessible only through its unnamed procedure.
The following sections describe each module type and how Panther executes it.
Widget modules are associated with individual widgets. You create and modify widget modules through the widget's JPL Validation property. This property is available for most widget types, including grids and groups. When you select this property, the JPL Program Text dialog box opens. You use the dialog box's editing window to enter and modify JPL code. For more information on using this editing window, refer to "Writing JPL in the Editor."
Panther executes a widget module only when it performs validation for the widget. In the case of data entry widgets such as text widgets, validation occurs when the user exits via TAB. For push buttons, radio buttons, check boxes, list boxes, and toggle buttons, validation occurs when the widget is clicked with the mouse or otherwise activated, for example, by the NL key. Because a widget module is accessible only to its widget, use it to perform tasks that are specific only to that widget.
The first procedure of a widget module must be unnamed. The unnamed procedure in a widget module is always this module's entry point. The module can also include named procedures; however, these can only be called by other procedures in the same module. When you save the module, the editor automatically compiles it. If an error prevents compilation, Panther issues a message and returns you to the JPL Program Text dialog box, where you must correct the error.
Because Panther saves the module as part of the widget, you can view and edit this module only through the editor. When you copy this widget to another screen or to the repository, Panther copies the module along with other widget data.
Panther calls a widget module after it executes the widget's validation function, if one exists. Panther first executes the module's unnamed procedure and passes the standard arguments associated with widget processing. For widgets such as single line text widgets, four arguments are passed that describe the widget and its current status: its field number, contents, occurrence number, and a set of context-sensitive flags. The unnamed procedure must have a parms statement in order to receive these arguments. For more information about arguments for different widget types, refer to "Calls from Screens and Widgets."
Screen modules are associated with specific screens. All the named procedures in a screen module are available to the application while the screen remains active. You create and modify screen modules through the screen's JPL Procedures property. When you select this property, the JPL Program Text dialog box opens. You use this dialog box's editing window to enter and modify JPL code. For more information on using this editing window, refer to "Writing JPL in the Editor."
The first procedure of a screen module can be unnamed; an unnamed procedure is optional. All subsequent procedures must be named. When you save the module, the editor automatically compiles it. If an error prevents compilation, Panther issues a message and returns you to the JPL Program Text dialog box, where you can correct the error.
Because Panther saves the module as part of the screen, you can view and edit this module only through the editor. If you save the screen as another file or as a repository entry, Panther copies the module along with all other screen data.
When you open a screen at runtime, Panther loads all its named procedures into memory. It then executes the screen module's unnamed procedure, if any. Panther passes the two standard arguments associated with screen processing to this procedure: the name of the screen and a set of context-specific flags. The unnamed procedure must have a While the screen is active—that is, displayed on top—every named procedure in its JPL module can be called. You can use these procedures to perform any task required by the screen.
Panther executes the unnamed procedure only when the screen first opens, after which it executes the global screen function and the screen's entry function, if any. Panther does not execute a screen module's unnamed procedure on subsequent exposures of an already open screen—for example, when a child or sibling screen closes.
Report modules are similar to screen modules; each report module is associated with a report and saved with the report binary. All named procedures in a report module are available while the report is running.
Unlike screen modules, all report procedures should be named and can be accessed by a corresponding call node in the report structure or called as a subroutine by another process.
You create and modify report modules through the report's JPL Procedures property. When you select this property, the JPL Program Text window opens. For more information on using this editing window, refer to "Writing JPL in the Editor." When you save the module, the editor automatically compiles it. If an error prevents compilation, Panther issues a message and returns you to the JPL Program Text window, where you can correct the error.
External modules are modules saved to disk in libraries or in a file and are therefore not saved or associated with any particular Panther screen. You can extract library modules and install them in the application's memory-resident list. Unlike widget and screen modules, external modules are available to the entire application at any time. Panther finds the modules in memory, in open libraries, or on disk. For details on the search order for library modules, refer to "Precedence of Called Objects."
External modules are accessible to the application in two ways:
Widget Modules
Executing Widget Modules
Screen Modules
Executing Screen Modules
parms
statement in order to receive these arguments. For more information about these arguments, refer to "Calls from Screens and Widgets."
Report Modules
External Modules
public
command. When Panther loads a public module, it loads the module's procedures into memory and executes its unnamed procedure, if any. The application can call any named procedure in a public module until it is removed from memory through the unload command.
You can create library JPL modules from within the editor (choose FileNewJPL) or with any text editor (and add them to a library). You can also write the contents of widget and screen JPL modules to a library, thereby making them accessible to other screens and to the application as a whole if necessary.
File modules can be stored in ASCII, in binary, or in an ASCII/binary format. Modules that are stored as ASCII files are easy to modify and are available to the entire application. However, because Panther must recompile the module each time it is called, an ASCII file module also incurs more processing time than screen or widget modules. To improve performance, precompile the module with jpl2bin. If an error occurs during compilation, Panther issues an error message and returns to the module's caller.
Panther compiles library modules when you save them from within the editor. The module is saved in binary format and Panther uses this compiled format at runtime. If the compiler finds syntax errors, it issues a warning and lets you save the module in an uncompiled format.
The source file is also stored to the library. Library module names should conform to operating system conventions. For filtering purposes, use a You can call a library module only if its library is already open (via sm_l_close or on startup via the SMFLIBS variable). Panther loads the module into memory each time you call it.
If you create the JPL module outside of the Panther environment, you can later store the module in a Panther library. To store a disk file module in an application library, you can perform either of the following procedures:
Library Modules
File Modules
Module Compilation
.jpl
extension on library modules that you create within the editor.
From the editor:
You can add a JPL module to an application's memory-resident list. Making a JPL module memory-resident reduces I/O time. The module is held in memory during the life of the application; therefore, ample memory might be required to run your application.
You add a module to the memory-resident list in these steps:
You must recompile your application after creating or editing a memory-resident list. For more information on memory-resident lists, refer to "Including Memory-Resident Components."
Writing JPL in the Editor |
JPL modules are created within the editor:
The JPL modules created through these properties are saved with the screen binary in an ASCII and binary format. The ASCII version allows you to view and edit the JPL; the binary version is used at runtime.
Selection of the screen and report JPL property invokes the JPL Program Text window, where you can examine and edit the JPL code currently stored with that property:
Screen- and report-level JPL is compiled and saved with the screen binary. Therefore, if the JPL compiler detects a syntax error, you must correct the error before you can save the module. However, you can save it to disk by choosing FileSave AsASCII Text File.
When writing or editing screen-and report-level JPL, you can take full advantage of the editor's File and Edit menu options.
To access the default text editor, choose Editor, or select the Direct to External Editor option to automatically open the window using the default text editor.
Widget-level JPL is compiled and saved with the screen binary. Therefore, if the JPL compiler detects a syntax error, you must correct the error before you can save the module. However, you can save it to disk by choosing the Save File button.
Since the widget-level JPL dialog box is modal, you cannot access the editor workspace menus.
You can create and edit library JPL modules within the editor by opening a library and then choosing FileNewJPL of FileOpenJPL to access an existing module. The JPL text dialog box opens.
The name of the module and the library in which it resides are displayed in the title bar in the form: Use the Edit menu options to copy, cut, and paste text, use FileSave options to save the module to an open library, or use FileSave AsASCII Text File to save the module as a disk file.
The JPL is compiled when you save the module to a library. If the compiler detects a syntax error, a warning is issued and you can choose to correct the error or save the module in an uncompiled format (Save AsASCII Text File) which you can collect later.
You can type your JPL directly into the dialog box, or you can invoke your local editor, for example, Notepad in Windows or vi in UNIX, by choosing EditExternal Editor (for widget-level JPL, choose the Editor button in the JPL Program Text window). If the OptionsDirect to External Editor option is selected, your preferred text editor is invoked immediately on entry into the JPL dialog box. The local editor is defined by the configuration variable You can also use your favorite text editor outside of the Panther workspace to write your JPL modules. Later you can compile the modules and import them to the appropriate library.
Note:
If you exceed the maximum line length of 253 characters, Panther issues an error message when you try to return to the dialog box and returns you to your editor to make the necessary corrections.
You can write and read code to and from disk files as well. To read a disk file into the JPL window, choose EditRead File (for widget-level JPL, choose the Insert File button). To save a JPL module to disk, choose FileSave AsASCII Text File (for widget-level, choose the Save File button. These invoke the Insert JPL Text File and save JPL Text File dialog boxes, respectively. When you read a disk file into a module, Panther inserts its contents at the cursor's current position.
To insert JPL from another library, choose EditInsert From Library (for widget-level, choose the Insert button).
The dialog box accepts line lengths of up to 253 characters. If you try to read from a file that contains longer lines, Panther copies all text preceding the erroneous line into the editing window, then issues an error message.
To compile and save a JPL module to its originating library, choose FileSave AsLibrary Member (for widget-level, choose the Insert button). If an error prevents compilation of a library module, a message is issued and you can correct the error or save the module in an uncompiled format which you can correct later.
To compile and save screen- and report-level JPL, choose FileCloseJPL (for widget-level, choose the OK button). If an error prevents compilation while compiling screen_ or widget-level JPL, the editor issues a message and returns you to the JPL dialog box.
Note:
Library modules that are referenced (by an include statement) within a module are not checked for compilation errors.
Screen- and Report-Level JPL
Figure 19-2 Create or edit screen-and report-level JPL in the JPL Program Text dialog box.
Widget-Level JPL
Figure 19-3 Create or edit widget-level JPL code in the JPL Program Text dialog box.
Library Modules
Figure 19-4 Library JPL modules can be created and updated from within the editor.
module@library_name
.
Using Your Own Editor
SMEDITOR
. When you exit the editor, you are returned to the JPL dialog box, which contains your latest edits.
Inserting JPL To and From Disk
Compiling and Saving
Calls |
An application can call JPL modules and their named procedures from various screen and widget hooks, and from control strings. The same calling options are available for any installed C or built-in function. Unless otherwise indicated, all references to procedures in this section apply equally to JPL procedures and installed C functions. For more information about installing C functions, refer to Chapter 20, "Writing C Functions."
Panther provides several ways of issuing calls:
You can also call JPL from C through the library function sm_jplcall.
A screen module's named procedures can be called from outside the module while the screen is active. Named procedures in library modules are accessible if the module is public; otherwise, the procedures can be called only by the module's unnamed procedure. Named procedures in a widget module can be called only by the module's unnamed procedure.
All calls can supply comma-delimited arguments to their corresponding parameters. Enclose the arguments in parentheses. If the procedure takes no arguments, use the void argument specifier (). You can pass the following as arguments:
Arguments
vars
command, widget names, and LDB entries.
@NULL
for any parameter in a C function that accepts NULL
as an argument.
Panther passes arguments by value, so changes to the receiving parameter's value leave its corresponding caller's argument unchanged. If you call an installed C function, you must prepare it for installation with the correct macro (
Note:
If the message file sets A procedure always returns to its caller with a return value—either integer, string, or double, according to the procedure definition. If the procedure lacks an explicit return statement, or the return statement omits a return argument, the procedure returns to its caller with a value of 0 or an empty string. If an execution error causes the procedure to return prematurely, it returns with -1.
You can specify modules and procedures in various properties of screens and widgets—for example, in a screen's Exit Function property. If you call a JPL module or procedure and supply no arguments, Panther automatically passes arguments that describe the state of the calling screen or widget. The called procedure must define the parameters needed to receive these arguments.
You can supply the same arguments to a C function if it is installed appropriately for the object that calls it. For example, if a C function is installed as a screen function, it can be called on screen entry and exit and receive arguments that describe the state of the screen. You can install C functions to be called from a screen, widget, group, or grid. For more information, refer to Chapter 44, "Installed Event Functions."
Table 19-1 describes the properties that can specify calls to a JPL procedure and the default arguments that are passed:
For example, if a widget's Exit Function property specifies the procedure The flag or flags that Panther passes are bit values, which you manipulate through JPL's bitwise operators SM_INTFNC
, SM_STRFNC
, SM_DBLFNC
, or SM_ZROFNC
) in order to pass arguments by value to that function. Refer to Chapter 20, "Writing C Functions," for more information about installing functions.
SM_DECIMAL
to a comma (,), insert a space between numeric constant arguments; otherwise, JPL interprets the comma that separates these arguments as a decimal point. Both methods shown in the following examples are equally successful in avoiding this problem:
ret = (1, 2)
ret = (3 ,4) Returns
Calls from Screens and Widgets
fld_xt
and no arguments are specified, Panther automatically passes in four arguments to this procedure; the second of these arguments is the widget's current value. fld_xt
gets this value in parameter val
and tests it as follows:
proc fld_xt (num, val, occ, flg)
{
if val = 'MR' sex = 'M'else sex = 'F'
return
}&
(AND
), |
(OR
), and ~
(one's complement). You can test these flags for conditional processing when you use the same procedure to handle different execution stages of a Panther object—for example, entry and exit of a widget. For information on flags that are set:
If a screen is memory-resident, Panther passes a null string to the called procedure instead of the screen's name.
You can use control strings to call procedures on specific input, for example, keyboard input or menu choices. You issue calls from a control string as follows:
where Panther compares name's return value to each For example, given this control string for a push button:
Panther calls the JPL module or procedure Refer to Chapter 18, "Programming Control Strings," for more detailed information about control string syntax.
You call a JPL procedure or module through the call command from other procedures or modules. The call command uses this syntax:
where Because JPL evaluates a procedure call to its return value, you can embed a procedure call within any expression. The following statement embeds a call to the You can also specify a procedure as an argument to another procedure. In the following statement, JPL first calls When Panther processes a call, it cannot know whether the called object is a JPL module, a JPL procedure, or an installed function. Panther attempts to execute a JPL call by searching for functions and JPL modules or procedures in this order:
Using a Memory-resident Screen
Calls from Control Strings
^
[
(target-string [
; target-string
]
) ] name [
(arg-spec
) ]
name
can be the name of a procedure or module, and
arg-spec
is one or more comma- or space-delimited arguments to pass to parameters in name
. The control string can optionally test the return value against one or more semicolon-delimited target strings. Each target string has this syntax:
[
test-value
= ] control-string
test-value
, reading from left to right. If it finds a match, it executes the specified control string. If you omit a test value, Panther executes the control string unconditionally. The control string can itself contain a JPL call with its own target strings; you can thereby nest multiple control strings with recursive calls.
^(-1=^(^jm_exit)cleanup; 1=&welcome_scr)process
process
when the user chooses this push button. It then evaluates the return value from process
to determine its next action: either to call cleanup
, or to invoke the welcome_scr
screen. On return from cleanup, Panther unconditionally calls the built-in function jm_exit
.
JPL Call Command
call
executable
( [arg-spec]
)executable
can be the name of a module or procedure, and arg-spec
is one or more comma-delimited arguments optionally to pass to parameters in executable
. The entire argument list is enclosed in parentheses.
Inline Calls
credit_eval
procedure:
if credit_eval() == 1
msg emsg "Creditworthy applicant"
else if credit_eval() == 0
msg emsg "Reject application"foobar
, then passes its return value into foo
as that procedure's second argument:
ret = foo(a, foobar(b), c)
Precedence of Called Objects
Variables |
JPL recognizes four kinds of variables:
This chapter shows how to declare and reference variables in JPL.
Earlier sections in this chapter showed how JPL declares parameter variables through the proc and parms commands. You can also declare a JPL variable with the vars command. JPL variables are not typed; you can assign a variable any string or numeric value. All values are stored as strings.
The vars command declares one or more JPL variables:
The following sections describe required and optional elements in a variable declaration.
Declaring JPL Variables
vars
var-spec [
, var-spec]
var-spec
specifies the variable's name and properties as follows:
var-name [
[num-occurs
]] [
(size
)] [
= init-value
]
var-name
[
num-occurs
]
num-occurs
occurrences. The default number of occurrences is 1. For example the following statement declares dependents as an array of ten occurrences:
vars dependents[10]
size
)
fname
with a size of 15 bytes:
vars fname (15)
If the value assigned to a variable is too large for its allocated size, Panther truncates it. For example, if fname
is programmatically assigned a value of Russell-Carrington
, it accepts only the first 15 characters, Russell-Carring
.
=
init-value
init-value
, where init-value
can be any constant, variable, or string or numeric expression. For example:
vars workweek = 5
vars avg_sale = @sum(sale_amt) / sale_amt->num_occurrences
vars name = fname##lname
If the variable is declared as an array, you can initialize its occurrences. For example:
vars ratings[5] = {"G", "PG", "PG-13", "R", "NC-17"}
Occurrence values are comma-delimited.
If no value is assigned, Panther initializes the variable to an empty string (""
).
You can declare global variables that are recognized throughout the application with the following syntax:
globalvar-spec [
,var-spec]
where var-spec
specifies the variable's name and properties as follows:
var-name [
[num-occurs
]] [
(size
)] [
=init-value
]
Like the vars command, global can declare multiple comma-delimited variables; each declaration can optionally declare the global as an array, specify its size (1 to 255 bytes), and assign its initial value.
To reinitialize or clear a global variable, declare it again.
Panther supplies several predefined variables where it stores application status information. These global variables (beginning with the character @
) are automatically defined at application startup and maintained by Panther.
After each dbms statement is executed, one group of global variables contains any error, warning, or status information returned by the database engine. Refer to "Variables for Logging Error and Status Information" for information on the variables, such as @dmengerrmsg, available through the database interface.
In the transaction manager, global variables contain information about transaction manager processing, such as the occurrence being processed. For more information, refer to Chapter 36, "Runtime Transaction Manager Processing."
When a Web browser makes a request in a Web application, the HTTP header fields are stored in global variables starting with the characters @cgi
. Refer to Chapter 11, "HTTP Variables," in the Web Development Guide for more information.
The @NULL
variable can be used for any parameter in a C function that accepts NULL
as an argument.
Caution:
The Panther @
variables can be updated frequently. If a variable's value is needed for further processing, copy its value to another location.
JPL's ability to reference a variable depends on the variable's scope and lifetime. LDB entries, widgets, and groups can be referenced by any module. LDB entries are available as long as their LDB remains loaded in memory. Widgets and groups are available as long as their screen is in memory. Global variables are available for the duration of the application.
Variables declared in an unnamed procedure are accessible to all procedures in the module; those declared in a named procedure are known only to that procedure.
Variables declared inside a procedure remain in memory until the procedure returns, while variables declared in the unnamed procedure remain in memory until the module returns. Two exceptions apply: variables declared in a screen module's unnamed procedure remain in memory until the screen exits; variables in a public module's unnamed procedure remain in memory until the module itself is removed from memory.
JPL's colon preprocessor expands any colon-prefixed variable to its literal value. This lets you reference variables in any JPL statement whose syntax otherwise excludes variables; for example, you can embed variables in a string. You can also supply JPL variables as arguments for several JPL commands that take only literal values as arguments, for example dbms and public.
The preprocessor expands colon-prefixed variables to their literal values before JPL executes the statement. For example, you can reference the variable acctno
in a msg
command, even though the command takes only a string value. For example:
msg emsg "I cannot find account number :acctno."
The colon preprocessor expands :acctno
to its assigned value before execution. Thus, if acctno
has a value of 91956, Panther executes the statement by displaying this message:
I cannot find account number 91956.
Conversely, the following statement:
msg emsg "I cannot find account number acctno."
yields this message:
I cannot find account number acctno.
Notes: The colon preprocessor always expands a variable to a string value. You can use this in order to force treatment of numeric values as strings.
A colon variable begins with a colon and ends with any non-expandable character, such as a blank or newline, as shown in the following syntax:
:var-name
Panther has two variations of colon variable syntax for applications that use its database interface, :+
and :=
. For more information on these, refer to "Colon Preprocessing."
To prevent expansion of variables that contain colons, prefix the colon with another colon (::
) or backslash (\:
), or follow it with a space. In the first two cases, the colon preprocessor discards the first colon or the backslash. In the third case, the colon and following space are preserved.
After Panther compiles and loads a JPL module, the colon preprocessor scans each statement from right to left for colons. When it finds one, it starts expansion during which it:
Parentheses explicitly delimit three scope of expansion. For example:
vars ref x4
vars alpha[3] = {"bits", "centuri", "rays"}
ref = "alpha"
x4 = :(ref)[3] // Now x4 = rays
The colon preprocessor expands :(ref)
to alpha
. JPL then assigns the value of alpha[3]
—rays
—to the variable x4
.
If a substring specifier immediately follows a variable name, the colon preprocessor gets the specified characters from the expanded value. If you enclose the variable name with parentheses, the colon preprocessor ignores the specifier, and JPL uses the specifier when it executes the statement.
For example, given these variables and assignments:
vars xyz = "Belgium"
vars xy = "New Zealand"
vars abc = "xyz"
vars m
the following statement assigns the value New Zealand
to variable m:
m = :abc(1, 2)
The colon preprocessor expands :abc(1, 2)
to the first two characters of the expanded value that is, it expands :abc
to xyz
, then extracts xy
from that value. After the expansion, JPL assigns to m
the value of xy
, which is New Zealand
.
By contrast, examine the following statement, where the expanded variable is enclosed by parentheses:
m = :(abc)(1, 2)
This time, the colon preprocessor expands :abc
to xyz
. After the expansion, JPL executes the substring specifier on the value of xyz
—Belgium
—and assigns its first two characters Be
to m
.
For more information, refer to "Substring Specifiers."
Colon preprocessing recognizes the subscript, or index, of an array reference as part of the variable and expands it accordingly. If an array reference omits the array's occurrence number, the colon preprocessor concatenates all the non-blank array occurrences and inserts a space between each pair of occurrence values.
The following examples show how Panther expands array references, given these variable declarations and assignments:
vars xyz[3] = {"alpha", "beta", "gamma"}
vars alpha[3] = {"bits", "centuri", "rays"}
vars v = "alpha"
vars w = "xyz"
vars x1 x2 x3 x4 x5
x1 = xyz[3] // x1 = gamma
:xyz[1]
to alpha
. Thus, :xyz[1][3]
becomes alpha[3]
. JPL changes the value of x2
to rays
:
x2 = :xyz[1][3] // x2 = alpha[3] = rays
v
to alpha
. x3
then equals the third occurrence of alpha
, which is rays
. The parentheses enclosing v
prevent the colon preprocessor from trying to expand the third occurrence of v
:
x3 = :(v)[3] // x3 = alpha [3] = rays
:v[3]
with the third occurrence of v
. Because v
has only one occurrence, Panther displays an error message:
x5 = :v[3] // error occurs because v[3] does not exist
xyz
, separating the occurrences with single blank spaces. :xyz
must be enclosed in quotes; otherwise, Panther displays an error message because beta
and gamma
are not variables:
x4 = ":xyz"
// x4 = ":xyz[1] :xyz[2] :xyz[3]" = "alpha beta gamma"
By default, the colon preprocessor evaluates colon-expanded text only once, even if the expanded text itself contains another colon reference. For example, the following code yields display of the message Thank Goodness, it's :day
:
vars day = "Friday"
vars period = "day"
msg emsg "Thank goodness it's :period"
To display the message Thank goodness it's Friday
, append an asterisk (*
) to the colon:
msg emsg "Thank goodness it's :*period"
When the colon preprocessor finds a reexpansion operator, it repeats expansion from the rightmost character of the expanded text. You can nest reexpansion operators to reexpand the same text more than once.
Constants |
JPL has the following constant types:
In addition to decimal numeric constants, Panther supports octal, hexadecimal, and binary numeric formats. Panther recognizes these formats through a number's leading characters, shown in Table 19-2:
Binary
Octal
Hexadecimal
If your application requires decimal numbers with leading zeros, you can turn off support for octal numbers by setting the setup variable OCTAL_SUPPORT to String constants are widely used in JPL, especially in msg and invocation statements. At runtime, JPL strips off the quote characters. You can use single or double quote symbols; however, the same symbol must open and close the string constant:
A quoted constant with no characters— To reference variable values in a string constant, use the colon preprocessor:
To use a special character in a quoted constant—colon, quote character, or backslash—prefix the character with a backslash.
Non-Decimal Number System Formats
Table 19-2 Non-decimal numeric formats supported by Panther
Numeric format
Leading characters
Example
0b, 0B
0b1 + 0b2 = 11
0
02 * 04 = 10
0x, 0X
0x3 * 0x5 = E
OCTAL_SUPPORT_OFF
. The default setting is OCTAL_SUPPORT_ON
.
Quoted String Constants
"55 Baker St."
'(212) 555-1212'""
or ''
is a null string.
"The amount is :total"
Setting Properties Using the Property API |
Panther objects and their properties can be referenced through JPL. For example, this if
statement conditionally unhides a widget (emp_salary
) at runtime by changing its hidden
property to PV_NO
:
if (login == "super")
emp_salary->hidden = PV_NO
The basic JPL syntax for referencing a Panther object and, optionally, any of its properties is as follows:
object-spec[
->property-spec]
The following sections describe syntactical elements and options.
You specify a Panther object either by its name or with object modifiers as follows:
object-name
@object-modifier
(object-identifier
)
For example, you can refer to the widget named last_name
as follows:
last_name
@widget("last_name")
Object modifiers make explicit the type of object required. Panther provides an @
modifier for each type of Panther object (except JPL variables): @widget
for widgets, @screen
for screens, and so on. Use these modifiers to avoid name conflicts—for example, between a screen that is being used simultaneously for data input and as an LDB. They are also useful for referencing objects whose names are otherwise considered illegal—for example, a screen whose name begins with a number. Thus, you can reference a screen with the name 1001.frm
as follows:
@screen("1001.frm")
Each object modifier takes either a string or integer argument. The argument can be a constant or variable, or an expression that evaluates to a string or integer. Table 19-3 lists the available modifiers and valid arguments for each.
If a widget or JPL variable is an array, you can reference occurrences and elements within that array. Occurrences are specified with the following syntax:
object-name
[n
]
@object-modifier
(object-identifier
)[n
]
Array elements are specified with the following syntax:
object-name
[[n
]]
@object-modifier
(object-identifier
)[[n
]]
The subscripts [n
] and [[n
]] indicate the occurrence and element to reference, respectively, where n
can be a signed (and for occurrences, unsigned) integer constant or expression. Occurrences and elements are both one-based. For example, @widget("customer")[3]
refers to the third occurrence in customers
, while @widget("customer")[[1]]
refers to the array's first element.
If a widget or JPL variable is an array but no occurrence is specified, Panther uses the default occurrence. When executing a field entry, field exit, or validation function, the default occurrence is the occurrence currently being processed. Otherwise, the default occurrence is 1.
Panther interprets an unsigned subscript as an absolute offset within an array. An unsigned subscript must be between 1
and the array's max_occurrences
property. Because references to an array element must be absolute, subscripts for element references are always unsigned.
Panther treats a signed subscript as a relative offset from the array's current occurrence. You can reference the current occurrence as array-name
[+0]
or array-name
[-0]
. For example, the following JPL procedure, called as array steps
's exit function, increments by 1 the value in steps
's current occurrence and puts it into the next occurrence:
proc nextOccData( widget_num, data, occ, context )
if ( occ < steps->max_occurrences )
{
steps[+1] = steps[+0] + 1
}
return
Relative references that use an expression for a subscript must enclose the expression in parentheses. For example steps[+(n)]
refers to the n
th occurrence after the current one in array steps
, while steps[(+n)]
refers to the array's n
th occurrence.
Although Panther assigns unique field numbers to elements within an array, any reference to these elements through their field number always evaluates to the array itself—that is, its first element. For example, the following array has three elements, which are numbered 1 through 3:
Given this array, the following statement puts Wilma
into variable data
:
data = @field_num(3)
To use field numbering to reference a given element's data, you must translate that field number into an occurrence number. For example:
proc getElemData()
vars cur_elem, i, elem_data, occ_no
// get the current element's field number
cur_elem = @screen()->fldnum
// get occurrence number of data in current element
for i = 1 while i <= @field_num(cur_elem)->array_size
{
if @field_num(cur_elem)[[i]]->fldnum = current_elem
{
occ_no = @field_num(cur_elem)->first_occurrence + i - 1
elem_data = @field_num(cur_elem)[occ_no]
}
}
If a named object's type is not made explicit, Panther searches for that object among the following Panther types, in this order:
You can join multiple object strings in a compound object string with the !
character. Compound object strings have this syntax:
object-string
!object-string
[ !object-string
]...
For example, the following object string specifies the customer
widget on the active window:
@screen("@current")!@widget("customer")
Compound object strings let you make the context of a Panther object as specific as you like and avoid possible ambiguity among different objects with the same name. For example, if two screens on the window stack—custqry.frm
and custedit.frm
—both have a cust_id
widget, you can uniquely identify each one as follows:
custqry.frm!cust_id
custedit.frm!cust_id
You can achieve even greater specificity within a compound object string by including object modifiers. For example, all of the following object strings are variants of custqry.frm!cust_id
:
custqry.frm!@widget("cust_id")
@screen("custqry.frm")!cust_id
@screen("custqry.frm")!@widget("cust_id")
Note:
You can reference objects through their object IDs with the @id
modifier; these unique handles provide a way to identify an object that is independent of its name and context.
An object's value is implicit in all references to it. In practice, this applies only to widgets that can have values. For example, you can get and set the contents of a text widget or a push button's label; widgets such as lines and boxes have no equivalent values that you can access.
In the case of arrays, subscripted references return the value of the specified occurrence or element; non-subscripted references return the first element. Thus, these two statements put the same data into variable cust
:
cust = @widget("customer")[[1]]
cust = @widget("customer")
You can get portions of an object's value by appending substring specifiers to the object's reference. For example, this statement gets the first eight characters from customer
's second occurrence:
cust = @widget("customer")[2](1, 8)
For more information about substrings, refer to "Substring Specifiers."
All Panther objects have properties that can be accessed with this syntax:
object-spec
->property-spec
The string that you supply for property-spec
contains at a minimum the JPL mnemonic for the desired property. For example, you can reference the current screen's title as follows:
@screen("@current")->title
If a property can be set to multiple values, property-spec
can specify one of them; for more information, refer to "Multi-item Properties." You can also specify a portion of a string property's setting; this is described in "Property Substrings."
Property specification can include the @property
modifier. For example, you can reference the current screen's title as follows
@screen("@current")->@property("title")
The @property
modifier is optional if you use the property's actual mnemonic; it is typically used in order to reference a property through a variable. For example, an all-purpose procedure that changes a widget's properties at runtime might look like this:
proc change_props (widg_name, prop, value)
@widget(widg_name)->@property(prop) = value
If a property is accessible through the editor, its JPL mnemonic is usually a variant of the name used in the Properties window, where all characters are in lower case, and non-alpha characters such as spaces, dashes, and slashes are replaced with underscores. For example, the Menu Name property is referenced as menu_name
.
A number of exceptions exist, usually for properties that share the same label in the Properties window. For example, if you set a widget's FG Color Type and BG Col or Type properties to Basic, both properties get Color Name as a subproperty. To differentiate these two properties, their runtime names are fg_color_name
and bg_color_name
, respectively. For a full list of runtime property names, refer to Chapter 1, "Runtime Properties," in Quick Reference.
Note: Several properties that are visible in the Properties window are not accessible at runtime—for example, the Inherit From and Columns properties.
Panther also provides access to a number of properties that are not available in the editor, either because they are accessible only at runtime or because they are application-wide (@app
) properties. For example, selected
is a runtime property that returns true or false for a specified occurrence in a list box or selection group; in_gui
is an application property that returns true if the application is running on a GUI platform and false if in character mode.
Refer to Chapter 1, "Runtime Properties," in Quick Reference for a list of all properties and their definitions.
Some properties have an array of values, for example, the Drop-Down Data property of combo boxes and option menus. To reference multi-item properties, specify the offset into that property's values as follows:
object-spec
->property-name
[prop-item
]
For example, the following code changes the selected item in an option menu that has its Drop-Down Source property set to constant data:
#replace current item with contents of "substitute"
vars count
for count = 1 \
while flavors->drop_down_data[count] != flavors
{}
flavors->drop_down_data[count] = substitute
flavors = flavors->drop_down_data[count]
To access control string assignments for a screen or for the application, use the desired logical key as the control_string
property's offset. For example, the following statement gets the screen-level control string assigned to the PF5 key:
ctrlstr = @screen("@current")->control_string[PF5]
Although properties cannot have properties, you can callsm_n_num_occurs
andsm_n_max_occur
for property expressions. For example:
drop_down_size =sm_n_num_occurs("optmenu->drop_down_data")
You can get and set a portion of a string property's value with the following syntax:
object-spec
->property-name
(offset
,length
)object-spec
->property-name
[prop-item
](offset
,length
)
For example, the following code conditionally assigns the first eight characters of a widget's name to its column_title
property:
if @field_num(i)->column_title = ""
@field_num(i)->column_title = @field_num(i)->name(1, 8)
Properties can be grouped into three general categories according to the types of values that they take:
Literal properties take any value—string, integer, or numeric, depending on the property. For example:
@widget("customers")->first_occurrence = 1
@screen("@current")->control_string[XMIT] = "^verify_acct"
Some properties have implied or explicit ranges. For example, you cannot set an array's first_occurrence
property to a value greater than the number of occurrences in the array.
Logical properties take a value of PV_YES (1)
or PV_NO (0)
. For example:
@widget("salary")->focus_protection = PV_YES
Enumerated properties can only be set to one of several predefined integer constants. For example, a widget's hidden property can be set to one of three constants: PV_YES
, PV_NO
, or PV_ALWAYS
.
For a full listing of runtime JPL property names and valid values, refer to Chapter 1, "Runtime Properties," in Quick Reference.
All widgets that contain data have a property that let you set its initial value—Initial Text for text widgets, Label for push buttons and check boxes, and so on. For most widget types, these need not be referenced explicitly. To access a widget's data, refer to the widget itself. For example, the following statements change the labels of check boxes day1
through day7
to the values found in successive elements of array lang
:
for count = 1 while count <= 7
@widget("day"##count) = @widget(lang)[count]
Table 19-4 shows which widget types are referenced directly in order to change their data, and the editor properties that set their initial data. There are accessible at runtime as implicit properties.
Notes:
Graph widget data is set by its Value Source property; this multi-item property must be explicitly referenced, for example, @widget("sales")->y_value_source[1]
.
Properties of an array's occurrences and elements can be accessed by subscripting the array reference—a single pair of square brackets refer to occurrences []
, double square brackets to elements [[]]
. For example, this statement toggles the reverse
property of an array's first element:
salaries[[1]]->reverse = !salaries[[1]]->reverse
In the editor, you can group together multiple radio buttons, check boxes or toggle buttons into a selection group. JPL identifies a selection group name as an array whose number of occurrences is equal to the number of selections from the group. Each array occurrence contains the number of the selected item: the first element contains the number of the first selected item, the second element contains the number of the next selection, and so on.
Groups can be set up to accept one, multiple, or no selections. If the group allows only one selection—its num_of_selections
property is set to PV_0_OR_1
or PV_1
—its corresponding JPL variable is an array with one occurrence of data, where group-name
[1]
contains the number of the selected item. Because single-selection groups have only one occurrence, JPL lets you omit the subscript. Thus, group-name
[1]
and group-name
are equivalent.
For example, days
is a selection group that allows multiple selections. It contains seven check box widgets with these labels:
[ ] MON [ ] TUE [ ] WED [ ] THU [ ] FRI [ ] SAT [ ] SUN
Panther numbers widgets in this group in order of their placement on the screen: MON
has a value of 1, TUE
a value of 2, and so on. If the user selects THU
and SUN
, days[1]
has a value of 4, while days[2]
has a value of 7.
You can programmatically evaluate and manipulate the contents of the group array. For example, the following code returns the number of items selected from days
, then passes each selection to the routine days_off
:
occurs = days->num_occurrences
for count = 1 while count <= occurs
{
call days_off( days[count] )
}
You can programmatically change group selections by setting group array occurrences to the desired values. The following code selects members 6 and 7—SAT
and SUN
—in group days
:
days[1] = 6
days[2] = 7
You can also use library functions sm_select and sm_deselect to change group selections. The following code is equivalent to the previous JPL:
call sm_select("days", 6)
call sm_select("days", 7)
If you place a widget inside a grid widget, the widget becomes an array whose size is determined by the number of occurrences assigned to the grid widget.
At runtime, the current selection inside of a grid widget can be determined by grid_current_occ
, a read-only property. The following JPL statement returns the number of the selected row in a grid named Detail
:
myvar=@widget("Detail")->grid_current_occ
When you use the transaction manager, it builds a tree of all table views that are linked to the root table view. It traverses this tree to issue transaction manager commands to each table view or server view. You can query traversal properties to get information about the table views, server views, and links that are a part of the current transaction.
The following JPL procedure queries the sv
property to ascertain the server view for the current widget on widget entry. It then executes the VIEW command to specify that server view:
proc get_sv_query
if K_ENTRY
{
vars value1
value1 = name->sv
call sm_tm_command("VIEW :value1")
}
return 0
If the specified property references an object that does not participate in the current transaction, Panther returns an error. For more information on traversal properties, refer to "Using Traversal Properties."
You can reference any JPL variable declared by the global
command at any time during the application. JPL also recognizes global variables defined in Panther header files—for example, logical key names such as XMIT
and EXIT
, and bit mask settings such as K_EXPOSE
and K_ENTRY
. You can reference these variables in any JPL expression and pass them as arguments to another procedure or function.
Caution: Because Panther uses these variables internally, avoid changing their values; doing so can yield unpredictable and possibly harmful results.
Data Types, Operators, and Expressions |
Data types describe how JPL uses the values of variables and constants. Operators specify what to do or how to manipulate variables and constants. Expressions combine variables and constants to produce new values.
JPL determines the data type of a variable or expression according to its value or usage. All variable values are stored as character strings; JPL converts those values when required.
JPL recognizes four data types:
The following sections summarize JPL operators, their operands, and the data type of the value after the operation. Associativity is left to right except for exponentiation, where it is right to left.
Operators
|
substring specifier |
|
concatenation |
date calculation | |
string length calculation | |
array sum | |
|
exponentiation |
|
division |
|
multiplication |
|
addition |
|
subtraction |
|
greater than |
|
greater than or equal to |
|
less than |
|
less than or equal to |
|
equal to |
|
not equal to |
|
|
|
Logical |
|
Logical |
|
one's complement |
|
bitwise |
|
bitwise |
JPL operators have the following precedence, in decreasing order:
() [] @date @length @sum
##
^
~ !
/ *
+ -
> >= < <=
== !=
&
&&
|
||
=
Some operators require operands of specific data types. If the operand's data type is different, JPL tries to convert it; otherwise an error occurs. In the case of relational and logical operators, JPL checks whether the operand data types are the same; if they are different but compatible—for example, integer and numeric—JPL converts them to one or the other; if they are incompatible, an error occurs.
Table 19-5 shows the data type that JPL uses for operands of compatible data types in relational and logical expressions:
Use the concatenation operator ## to join multiple values into a single string. For example, these statements concatenate the string Blue Moon
into variable a
.
vars a = "Blue "
vars b = "Moon"
a = a##b
Substring specifiers let you reference any part of a string that is in a variable or property. Specify a substring with the following syntax:
obj-name
(offset
,length
)
obj-name
offset
obj-name
, where the first character in obj-name
is 1. A value for offset
is required, and can be an integer or integer expression.
length
length
exceeds the substring's actual length, JPL reads only up to the last byte of data. A value for length
is optional: if no argument is supplied, JPL operates on all characters from offset to the end of the string.
The following examples show some common uses for substring specifiers:
if int_phone(1, 3) == "039"
country = "Italy"
for i = 1 while string(i, 1) != " "
{ }
Notes:
If the message file sets zip(6) = "-"##extension
SM_DECIMAL
to a comma (,), insert a space between numeric constant arguments; otherwise, JPL interprets the comma that separates these arguments as a decimal point. The space can either precede the comma or follow it.
The For example, if widgets In the next example, If an operand includes a time value—for example, The @ For example, the following statement gets the total number of characters in The JPL provides three operators for bit manipulation: For example, this procedure tests the value of widget status flags The next procedure examines the settings of For more information on the flag settings that Panther passes into widget and screen modules and hook functions, refer to "Calls from Screens and Widgets" and Chapter 44, "Installed Event Functions."
An expression produces a new value by combining constants, variables, and operators. In all statements, Panther's colon preprocessor evaluates colon-expand ed variables. In all expressions, JPL's statement processor replaces variable names with values. Evaluation is generally from left to right; however, you can affect order of evaluation through parentheses.
JPL evaluates an expression as one of four data types: string, numeric, bitwise, or logical. However, it is an error to combine a string assignment with a numeric assignment for a single variable within one expression. The following sections discuss these data types.
A string expression combines one or more quoted string constants or values of string variables. Substring specifiers and A numeric expression combines variables and numeric constants with one or more of the numeric operators. The following examples are numeric expressions:
If the setup variable where For example, the following statement assigns 1.667 to
Notes:
Panther uses the If A bitwise expression uses variables or constants which have the data type integer, and any of the bitwise operators. The following examples are bitwise expressions:
A logical expression uses logical and relational operators to evaluate variables, numeric constants, integer constants, string expressions, numeric expressions, or integer expressions. Operands must be of the same data type; otherwise, JPL tries to convert them according to Table 19-5. For example, you can compare a numeric literal to a variable or expression only if JPL can evaluate the variable or expression to a numeric. Otherwise, it displays an error message.
The following examples are logical expressions:
In contrast to C, the JPL interpreter always fully evaluates a boolean expression. In the following example, JPL calls @date
@date
operator lets you compare and perform arithmetic on dates. This operator uses a date as its operand—either a widget with a date format, or a date string constant or expression. @date
converts a date constant to a numeric by counting the number of days between the date constant and January 1, 1753—the standard for date calculations.
order-date
and ship-date
have date edits, you can add 30 days to order-date
's value and assign it to ship-date
:
ship-date = @date(order-date) + 30
today
is a widget with the current date, and days
is a variable that gets the number of days between today and 4/1/96:
days = @date("4/1/1996") - @date(today)
02/22/94 10:15
—@date
ignores the time value and outputs only a date value.
@length
@length
operator counts the number of characters in one or more string arguments. You can supply string constants or variables as arguments. You can use a substring specifier on any argument that is a variable.
length
counts all characters and embedded blanks. Leading blanks in right-justified widgets and trailing blanks in left-justified widgets are ignored. In quoted string constants, leading blanks are counted but trailing blanks are ignored.
fname
and lname
:
vars ln
ln = @length(@widget("fname"), @widget("lname")) @sum
@sum
operator calculates the sum of all non-blank occurrences in an array. In the next statement, quantities
is an array and total
is a widget that gets the sum of occurrences in quantities
:
total = @sum(quantities)
Bitwise Operators
AND
(&
), OR
(|
), and one's complement (~
). Bitwise operators let you examine and set the flags that are set on bit masks.
K_ENTRY
and K_EXIT
to determine whether the widget is being entered or exited:
proc field_func (number, data, occ, flags)
if flags & K_ENTRY
jpl do_process
else if flags & K_EXIT
jpl do_exit_process
returnK_KEYS
to determine which key the user pressed to exit a widget:
proc field_func2(num, dat, occ, flags)
if (flags & K_KEYS) == K_NORMAL
return
else if (flags & K_KEYS) == K_ARROW
msg emsg "Please use the tab key to move between fields."
return Expressions
String Expressions
##
are string operators. The following examples are all string expressions:
'Montreal'
"Processed :i items"
fname##' '##lname
telephone(1, 3) Numeric Expressions
y + z
@sum(quantities)
@length(fname,lname)
x^y + y * (z^3/4 + 1) - x/2
86DECIMAL_PLACES
is set to a number, JPL rounds the value of a numeric expression to that number of decimal places. You can change this with a format specifier to declare the total length and the number of decimal places. Format specifiers have this syntax:
%
[
t ] [m] [
.n]
var-name
m
and n
are integer constants or variables. m
specifies the total number of characters, including leading spaces, sign, digits, and decimal place. If you omit m
, or m
is too small to output the variable's value, JPL uses the variable's size. n
specifies the number of digits after the decimal place. If you omit n
, JPL uses 2 decimal places.
i
.
%6.3 i = 10/6 // rounds value to 1.667
t
overrides rounding and truncates to the specified number of decimal places, if any. For example, the following statements truncate the values assigned to variables i
and n
:
%t1.2 i = 10/6 // truncates i to 1.66
%t1.0 n = 10/6 // truncates n to 1sprintf()
function to perform rounding. Because this function's behavior is compiler-specific, rounding results for 0.5 decimals can vary among different platforms.
var-name
is a widget or LDB entry, you can define its floating point precision by setting Data Formatting (data_formatting
) to PV_NUMERIC
and setting its Format Type property. At validation, Panther uses this property to format the widget's value.
Bitwise Expressions
flag1 & flag2
x | mask Logical Expressions
y
x != 7
(total * (1 + tax)) <= max_value
flag > ~flagmyFunc
even though the expression already evaluates to true:
vars a = 1
if ( a || myFunc() )
...
JPL Commands |
All the JPL commands are fully described in Chapter 2, "JPL Command Reference," in Programming Guide. In general, command arguments can be either variables or strings. String arguments must be enclosed in single or double quotes. To use a variable's value within a string, you can append a colon to the variable (colon preprocessing). For more information, refer to "Colon Preprocessing."
Optimization |
You can improve performance of JPL procedures in several ways:
bin2c
, and then add it to Panther's memory-resident list with sm_formlist.
for i = 1 while i < 10
{
...
}
while i < 10
{
...
i = i + 1
}\
) or an extra colon (:
) because Panther avoids copying the argument to a buffer to remove extra characters.