This repository has been archived by the owner on Jan 19, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
spp.txt
2063 lines (1302 loc) · 70.7 KB
/
spp.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
A Reference Manual
for the
IRAF Subset Preprocessor Language
Douglas Tody
Kitt Peak National Observatory*
January 1983
(revised September 1983)
ABSTRACT
The IRAF subset preprocessor language (SPP) implements
a subset of the proposed full IRAF scientific programming
language. This paper defines the language and gives
several examples of procedures written in the language.
The differences between the subset language and the full
language are summarized. IRAF tasks or programs are
discussed, and a working example of an IRAF program is
shown. The XC compiler for the SPP language on the UNIX
software development system is introduced.
_______________
*Kitt Peak National Observatory is operated by the Association of
Universities for Research in Astronomy, Inc. under contract with the
National Science Foundation.
SPP (Jan83) IRAF Subset Preprocessor Language SPP (Jan83)
Contents
1. Introduction 1
2. Getting Started 1
3. Fundamentals of the Language 2
3.1 Lexical Form 2
3.1.1 comments 2
3.1.2 continuation 2
3.1.3 integer constants 2
3.1.4 floating point constants 3
3.1.5 character constants 3
3.1.6 string constants 4
3.1.7 identifiers 4
3.2 Data Types 5
3.3 Declarations 5
3.3.1 variable, array, and procedure declarations 5
3.3.2 array declarations 6
3.3.3 string declarations 6
3.3.4 global common declarations 7
3.3.5 procedure declarations 7
example 1: the sinc function 8
3.3.6 multiple entry points 8
example 2: multiple entry points 9
3.4 Initialization 9
3.5 Control Flow Constructs 9
3.5.1 conditional execution 10
3.5.2 error handling 11
3.5.3 repetitive execution 13
3.6 Expressions 14
3.6.1 mixed mode expressions 15
3.6.2 type coercion 16
3.7 The Assignment Statement 16
3.8 Some Examples 16
example 3: length of a string 16
example 4: min and max of a real array 17
3.9 Program Structure 18
3.9.1 include files 18
3.9.2 macro definitions 19
3.9.3 the task statement, and tasks 20
3.9.4 help text 21
4. Anachronisms 22
5. Notes on Topics not Discussed 23
APPENDIX A: Predefined Constants 24
APPENDIX B: Detailed Examples 25
Example 5: Matrix Inversion 25
Example 6: Pattern Matching 27
Example 7: Error Handling 31
SPP (Jan83) IRAF Subset Preprocessor Language SPP (Jan83)
1. INTRODUCTION
The IRAF subset preprocessor language (SPP) implements a subset of
the proposed IRAF preprocessor language, described in the paper "The
Role of the Preprocessor". The subset does not include pointers,
structures, and dynamic and virtual arrays. Subset preprocessor
programs should be written with eventual conversion to the full
preprocessor language in mind. In general, this conversion will not
be difficult, provided one generates simple and straightforward code.
One of the best ways to learn to program in a new language is to read
the source listings of existing programs. Many examples of
procedures, programs, and packages written in the SPP language can be
found in the IRAF system source directories. We shall only attempt to
summarize the basic features of the language here.
2. GETTING STARTED
The best way to get started is to build and run a simple program,
before attempting to learn all the details of the language. Here is
our version of the "hello world" program from the C book:
# Simple program to print "hello, world" on the standard
# output.
task hello # CL callable task
procedure hello() # common procedure
begin
call printf ("hello, world\n")
end
On the UNIX system, this program would be placed in a file with the
extension ".x" and compiled with the command XC (X Compiler) as
follows.
xc hello.x
The XC compiler will translate the program into Fortran, call the
Fortran compiler to generate the object file ("hello.o"), and call the
loader to link the object file with modules from the IRAF system
libraries to produce the executable program "hello". XC may be used
to compile C and Fortran programs as well as X programs, and in
general behaves very much like CC or F77 (note that the "-o" flag is
not required; by default the name of the output module is the base
name of the first file name on the command line). The "-F" flag may
be used to inspect the Fortran generated by the preprocessor; this is
sometimes necessary to interpret error messages from the F77 compiler.
-1-
SPP (Jan83) IRAF Subset Preprocessor Language SPP (Jan83)
3. FUNDAMENTALS OF THE LANGUAGE
The SPP language is based on the Ratfor language. The lexical
form, operators, and control flow constructs are identical to those
provided by Ratfor. The major differences are the data types, the form
of a procedure, the addition of inline strings and character
constants, the use of square brackets for arrays, and of course the
TASK statement. The i/o facilities provided are quite different.
3.1 LEXICAL FORM
A subset preprocessor program consists of a sequence of lines of
text. The length of a line is arbitrary, but the SPP is guaranteed to
be able to handle only lines of up to 160 characters in length. The
end of each line is marked by the NEWLINE character. Both upper and
lower case characters are permitted. Case is significant.
WHITESPACE is defined as one or more tabs or spaces. Newline normally
marks the end of a statement, and is not considered to be whitespace.
Whitespace always delimits tokens, i.e., keywords and operators will
not be recognized as such if they contain embedded whitespace.
3.1.1 COMMENTS
A comment begins with the character # and ends at the end of the
line.
3.1.2 CONTINUATION
Statements may span several lines. A line which ends with an
operator (excluding '/') or punctuation character (comma or
semicolon) is automatically understood to be continued on the
following line.
3.1.3 INTEGER CONSTANTS
A decimal integer constant is a sequence of one or more of the
digits 0-9. An octal constant is a sequence of one or more of the
digits 0-7, followed by the letter 'b' or 'B'. A hexadecimal
integer constant is one of the digits 0-9, followed by zero or more
of the digits 0-9, the letters a-f, or the letters A-F, followed by
the letter 'x' or 'X'. The following notation more concisely
summarizes these definitions:
-2-
SPP (Jan83) IRAF Subset Preprocessor Language SPP (Jan83)
decimal constant [0-9]+
octal constant [0-7]+('b'|'B')
hexadecimal constant [0-9][0-9a-fA-F]*('x'|'X')
identifier [a-zA-Z][a-zA-Z_0-9]*
In the notation used above, "+" means 1 or more, "*" means zero or
more, "-" implies a range, and "|" means "or". Brackets ("[]")
define a class of characters. Thus, "[0-9]+" reads "one or more of
the characters 0 through 9".
3.1.4 FLOATING POINT CONSTANTS
A floating point constant (type REAL or DOUBLE) consists of a decimal
integer, followed by a decimal point, followed by a decimal fraction,
followed by one of (e|E|d|D), followed by a decimal integer, which
may be negative. Either the decimal integer or the decimal fraction
part must be present. The number must contain either the decimal
point or the exponent (or both). Embedded whitespace is not
permitted.
The following are all legal floating point numbers:
.01
100.
100.01
1E5
1E-5
1.00D5
1.0D0
A floating constant may also be given in sexagesimal format, i.e.,
in hours and minutes, or in hours, minutes, and seconds. The number
of colon separated fields must be two or three, and the number of
decimal digits in the second field and in the integer part of the
third field is limited to exactly two. The decimal point is
optional.
00:01 = 0.017
00:00:01 = 0.00028
01:00:00 = 1.0
01:00:00.00 = 1.0
3.1.5 CHARACTER CONSTANTS
A character constant consists of from 1 to 4 digits delimited at
front and rear by the single quote ("'", as opposed to the double
quotes used to delimit string constants). A character constant is
numerically equivalent to the corresponding decimal integer, and may
be used wherever an integer constant would be used.
-3-
SPP (Jan83) IRAF Subset Preprocessor Language SPP (Jan83)
'a' integer equivalent of the letter 'a'
'\n' integer equiv. of the newline character
'\007' the octal integer 07B
'\\' the integer equiv. of the character '\'
The backslash character ("\") is used to form "escape sequences".
The following escape sequences are defined:
\b backspace
\f formfeed
\n newline
\r carriage return
\t tab
3.1.6 STRING CONSTANTS
A string constant is a sequence of characters enclosed in double
quotes. The double quote itself may be included in the string by
escaping it with backslash. All of the escape sequences given above
are recognized. The backslash character itself must be escaped to
be included in the string. A string constant may not span several
lines of text.
3.1.7 IDENTIFIERS
An identifier is an upper or lower case letter, followed by zero or
more upper or lower case letters, digits, or the underscore
character. Identifiers may be as long as desired, but only the
first five characters and the last character are significant.
The following identifiers are reserved (though some are not actually
used at present):
auto do include short
begin double int sizeof
bool else long static
break end map struct
call entry next switch
case extern plot task
char false printf true
clgetpar for procedure union
clputpar getpix putpix unmap
common goto real until
complex if repeat virtual
data iferr return vstruct
define imstruct scan while
-4-
SPP (Jan83) IRAF Subset Preprocessor Language SPP (Jan83)
3.2 DATA TYPES
The subset preprocessor language supports a fairly wide range of
data types. The actual mapping of an XPP data type into a Fortran
data type depends on what the target compiler has to offer.
XPP Data Types
bool boolean (Fortran LOGICAL)
char character (8 bit signed)
short short integer
int integer (Fortran INTEGER)
long long integer
real single precision floating (Fortran REAL)
double double precision floating (DOUBLE PRECISION)
complex single precision complex (Fortran COMPLEX)
The only permissible values for a boolean variable are "true" and
"false". The CHAR data type belongs to the family of integer data
types, i.e., a CHAR variable or array behaves like an integer variable
or array. The value of a CHAR variable may range from -127 to 127.
CHAR and SHORT are signed integer data types (i.e., they may take on
negative values).
In addition to the seven primitive data types, the SPP language
provides the abstract type POINTER. The SPP language makes no
distinction between pointers to different types of objects, unlike
more strongly typed languages such as C (and the full preprocessor).
The SPP implementation of the POINTER data type is a stopgap measure.
3.3 DECLARATIONS
The SPP language implements named procedures with formal parameters
and local variables. Global common and dynamic memory allocation may
be used to share data amongst procedures. A procedure may return a
value, but may not return an array or string. Declarations are
included for procedures, variables, arrays, strings, typed procedures,
external procedures, and global common areas. Storage for local and
global variables and arrays may be assumed to be statically allocated.
3.3.1 VARIABLE, ARRAY, AND FUNCTION DECLARATIONS
Although the language does not require that parameters be declared
before local variables and functions, it is a good practice to
follow. The syntax of a type declaration is the same for parameters,
variables, and procedures.
type_spec object [, object [,... ]]
Here, "type_spec" may be any of the seven primitive data types, a
-5-
SPP (Jan83) IRAF Subset Preprocessor Language SPP (Jan83)
derived type such as POINTER, or EXTERN. A list of one or more data
objects follows. An object may be a variable, array, or procedure.
The declaration for each type of object (variable, array, or
procedure) has a unique syntax, as follows:
variable identifier
array identifier "[" dimension_list "]"
procedure identifier "()"
Procedures may be passed to other procedures as formal parameters. If
a procedure is to be passed to a called procedure as a formal
parameter, it must be declared in the calling procedure as an object
of type EXTERN.
3.3.2 ARRAY DECLARATIONS
Arrays are one-indexed. The storage order is fixed in such a way
that when the elements of the array are accessed in storage order, the
leftmost subscript varies fastest. Arrays of up to three dimensions
are permitted.
The size of each dimension of an array may be specified by any compile
time constant expression, or by an integer parameter or parameters, if
the array is a formal parameter to the procedure. If the array is
declared as a formal parameter, and the size of the highest dimension
is unknown, the size of that dimension should be given as ARB (for
arbitrary).
real data[ARB] # length of array is unknown
short raster[NPIX*2,128] # 2-dim array
The declared dimensionality of an array passed as a formal parameter to
a procedure may be less than or equal to the actual dimensionality of
the array.
3.3.3 STRING DECLARATIONS
A string is an EOS delimited array of type CHAR (EOS stands for
End Of String). Strings may contain only character data (values 0
through 127 decimal), and must be EOS delimited. A character string
may be declared in either of two ways, depending on whether
initialization is desired:
char input_file[SZ_FNAME]
string legal_codes "efgdox"
The preprocessor automatically adds 1 to the declared array size, to
allow space for the EOS marker. The space used by the EOS marker is
not considered part of the string. Thus, the array "char x[10]" will
contain space for ten characters, plus the EOS marker.
-6-
SPP (Jan83) IRAF Subset Preprocessor Language SPP (Jan83)
3.3.4 GLOBAL COMMON DECLARATIONS
Global common provides a means for sharing data between separately
compiled procedures. The COMMON statement is a declaration, and must
be used only in the declarations section of a procedure. Each
procedure referencing the same common must declare the common in the
same way.
common /common_name/ object [, object [, ... ]]
To avoid the possiblity of two procedures declaring the same common
area differently in separate procedures, the COMMON declaration should
be placed in a INCLUDE file (include files are discussed in a later
section).
3.3.5 PROCEDURE DECLARATIONS
The form of a PROCEDURE declaration is shown below. The
"data_type" field must be included if the procedure returns a value.
The BEGIN keyword separates the declarations section from the
executable body of the procedure, and is required. The END keyword
must follow the last executable statement.
[data_type] PROCEDURE proc_name ([p1 [, p2 [,... ]]])
(declarations for parameters)
(declarations for local variables and functions)
(initialization)
BEGIN
(executable statements)
END
All parameters, variables, and typed procedures must be declared. The
XPP language does not permit implicit typing of parameters, variables,
or procedures (unlike Fortran).
If a procedure has formal parameters, they should agree in both number
and type in the procedure declaration and when the procedure is
called. In particular, beware of SHORT or CHAR parameters in argument
lists. An INT may be passed as a parameter to a procedure expecting a
SHORT integer on some machines, but this usage is NOT PORTABLE, and is
not detected by the compiler. The compiler does not verify that a
procedure is declared and used consistently.
If a procedure returns a value, the calling program must declare the
procedure in a type declaration, and reference the procedure in an
expression. If a procedure does not return a value, the calling
program may reference the procedure only in a CALL statement.
-7-
SPP (Jan83) IRAF Subset Preprocessor Language SPP (Jan83)
EXAMPLE 1: THE SINC FUNCTION
This example demonstrates how to declare a typed procedure, which
in this case returns a single real value. Note the inclusion of the
double parenthesis ("()") in the declaration of the function SIN, to
make it clear that a function is being declared, rather than a local
variable. Note also the use of the RETURN statement to return the
value of the function SINC.
real procedure sinc (x)
real x
begin
if (x == 0.0)
return (1.0)
else
return (sin(x) / x)
end
3.3.6 MULTIPLE ENTRY POINTS
Procedures with multiple entry points are permitted in the subset
preprocessor language because they provide an attractive alternative to
global common when several procedures must have access to the same
data. The multiple entry point mechanism is a primitive form of block
structuring. The advantages of multiple entry points over global
common are:
(1) Access to the database is restricted to calls to the defined
entry points. A secure database can thus be assured.
(2) Initialization of data in a procedure with multiple entry
points is permissible at compile time, whereas global common
cannot (reliably) be initialized at compile time.
Nonetheless, the multiple entry point construct is only useful for
small problems. If the problem grows too large, an enormous procedure
with many entry points results, which is unacceptable.
The form of a procedure with multiple entry points is shown below.
Either all entry points should be untyped, as in the example, or all
entry points should return values of the same type. Control should
only flow forward. Each entry point should be terminated by a RETURN
statement, or by a GOTO to a common section of code which all entry
points share. The shared section of code should be terminated by a
single RETURN which all entry points share.
-8-
SPP (Jan83) IRAF Subset Preprocessor Language SPP (Jan83)
Example 2: Multiple Entry Points
procedure push (datum)
int datum # value to be pushed or popped
int stack[SZ_STACK] # the stack
int sp # the stack pointer
data sp/0/
begin
(push datum on the stack, check for overflow)
return
entry pop (datum)
(pop stack into "datum", check for underflow)
return
end
3.4 INITIALIZATION
Local variables, arrays, and character strings may be initialized
at compile time with the DATA statement. Data in a global common may
NOT be initialized at compile time. If initialization of data in a
global common is required, it must be done at run time by an
initialization procedure.
The syntax of the DATA statement is defined in the Fortran 77 standard.
Some simple examples follow.
real x, y[2]
char ch[2]
data x/0/, y/1.0,2.0/, ch/'a','b',EOS/
3.5 CONTROL FLOW CONSTRUCTS
The subset preprocessor provides a full set of control flow
constructs, such as are found in most modern languages. Some of these
have already appeared in the examples.
An SPP control flow construct executes a "statement" either
conditionally or repetitively. The "statement" to be executed may be
a simple one line statement, a COMPOUND STATEMENT enclosed in curly
brackets or braces ("{}"), or the NULL STATEMENT (";" on a line by
itself).
conditional constructs: IF, IF ELSE, SWITCH CASE
repetitive constructs: DO, FOR, REPEAT UNTIL, WHILE
branching: BREAK, NEXT, GOTO, RETURN
-9-
SPP (Jan83) IRAF Subset Preprocessor Language SPP (Jan83)
Two special statements are provided to interrupt the flow of control
through one of the repetitive constructs. BREAK causes an immediate
exit from the loop, by jumping to the statement following the loop.
NEXT shifts control to the next iteration of the loop. If BREAK and
NEXT are embedded in a conditional construct, which is in turn
embedded in a repetitive construct, it is the outer repetitive
construct which will define where control is shifted to.
3.5.1 CONDITIONAL EXECUTION
The IF and IF ELSE constructs are shown below. The "expr" part
may be any boolean expression. The "statement" part may be a simple
statement, compound statement enclosed in braces, or the null
statement. The control flow constructs may be nested indefinitely.
if (expr) IF construct
statement
if (expr) IF ELSE construct
statement
else
statement
The ELSE IF construct is useful for selecting one statement to be
executed from a group of possible choices. This construct is a more
general form of the SWITCH CASE construct.
if (expr) ELSE IF construct
statement
else if (expr)
statement
else if (expr)
statement
The SWITCH CASE construct evaluates an integer expression once, then
branches to the matching case. Each case must be a unique integer
constant. The maximum number of cases is limited only by table space
within the compiler.
A case may consist of a single integer constant, or a list of integer
constants, delimited by the character ":". The special case DEFAULT,
if included, is selected if the switch value does not match any of the
other cases. If the switch value does not match any case, and there
is no default case, control passes to the statement following the body
of the SWITCH statement.
Each case of the SWITCH statement may consist of an arbitrary number of
statements, which do not have to be enclosed in braces. The body of
-10-
SPP (Jan83) IRAF Subset Preprocessor Language SPP (Jan83)
the switch statement, however, must be enclosed in braces as shown.
switch (int_expr) { SWITCH CASE construct
case int_const_list:
statements
case int_const_list:
statements
default:
statements
}
example:
switch (operator) {
case '+':
c = a + b
case '-':
c = a - b
default:
call error (1, "unknown operator")
}
The SWITCH construct will execute most efficiently if the cases form a
monotonically increasing sequence without large gaps between the cases
(i.e., case 1, case 2, case 3, etc.). The cases should, of course, be
defined parameters or character constants, rather than explicit
numbers.
3.5.2 ERROR HANDLING
The SPP language provides support for error actions, error handling
and error recovery. Knowledge of the SPP error handling procedures is
necessary to correctly deal with error actions initiated by the system
library routines.
A recoverable error condition is asserted by a call to the ERROR
statement. An irrecoverable error condition is asserted with the
FATAL statement. Error recovery is implemented using the IFERR and
IFNOERR statements. If an error handler is not "posted" by a call to
IFERR or IFNOERR, a system defined error handler will be called,
returning system resources, closing files, deleting temporary files,
and aborting the program.
-11-
SPP (Jan83) IRAF Subset Preprocessor Language SPP (Jan83)
errchk proc1, proc2, ... # errchk declaration
iferr (procedure call or assignment statement)
<error_action_statement>
iferr {
<any statements, including IFERR>
} then
<error_action_statement>
Language support includes the IFERR and IFNOERR statements and the
ERRCHK declaration. The IFERR and IFNOERR statements are gramatically
equivalent to the IF statement. The meaning of the IFERR statement is
"if an an error occurs during the processing of the enclosed
code,...". IFNOERR is equivalent, except that the sense of the test
is reversed. Note that the condition to be tested in an IFERR
statement may a single or compound procedure call or assignment
statement, while the IF statement tests a boolean expression.
If a procedure calls a subprocedure which may directly or indirectly
take an error action, then the subprocedure must be named in an ERRCHK
declaration in the calling procedure. If an error occurs during the
processing of a subprocedure and an error handler is posted somewhere
back up the chain of procedure calls, then control must revert
immediately back up the chain of procedures to the procedure which
posted the error handler. This will work only if all intermediate
procedures include ERRCHK declarations for the next lower procedure in
the chain.
Graphically, assume that procedure A calls B, that B in turn calls C,
and so on as shown below:
A (A posts error handler with IFERR)
B (B must ERRCHK procedure C)
C (C must ERRCHK procedure D)
D (D calls ERROR)
As indicated by the diagram, procedure D calls ERROR, "taking an error
action". If no handler is posted, the error action will consist of the
system error recovery actions, terminating with the abort of the
current program. But if an error handler is posted, as is done by
procedure A in the example, then control should revert immediately to
procedure A. The error handler in A might try again with slightly
different parameters, perform special cleanup actions and abort, print
a more meaningful error message and take another error action, print a
warning message, or whatever. If the ERRCHK declaration is omitted in
procedure B or C, control will not revert immediately to procedure A,
and processing will erroneously continue in the intermediate
procedure, as if an error had not occurred.
Several library procedures are provided in the system library for use
in error handlers. The ERRACT procedure may be called in an error
-12-
SPP (Jan83) IRAF Subset Preprocessor Language SPP (Jan83)
handler to issue the error message posted by the original ERROR call as
a warning message, or to cause a particular error action to be taken.
The error actions are defined in the include file "<error.h>".
ERRCODE returns either OK or the integer code of the posted error.
Library procedures related to error handling:
error (errcode, error_message) (language)
fatal (errcode, error_message) (library)
erract (severity) (library)
val = errcode () (library)
ERRACT severity codes <error.h>
EA_WARN # issue a warning message
EA_ERROR # assert recoverable error
EA_FATAL # assert fatal error
An arithmetic exception (X_ARITH) will be trapped by an IFERR
statement, provided the posted handler(s) return without causing error
restart. X_INT and X_ACV (interrupt and access violation may be
caught only by posting an exception handler with XWHEN.
3.5.3 REPETITIVE EXECUTION
An assortment of repetitive constructs are provided for
convenience. The simplest constructs are WHILE, which tests at the
top of the loop, and REPEAT UNTIL, which tests at the bottom. The DO
construct is convienent for simple sequential operations on arrays.
The most general repetitive construct is the FOR statement.
while (expr) WHILE construct
statement
repeat { REPEAT UNTIL
statements
} until (expr)
repeat { infinite REPEAT loop
statements (exit with BREAK, RETURN, etc)
}
The FOR construct consists of an initialization part, a test part, and
a loop control part. The initialization part consists of a statement
which is executed once before entering the loop. The test part is a
boolean expression, which is tested before each iteration of the loop.
The loop control statement is executed after the last statement in the
-13-
SPP (Jan83) IRAF Subset Preprocessor Language SPP (Jan83)
body of the FOR, before branching to the test at the beginning of the
loop. When used in a FOR statement, NEXT causes a branch to the loop
control statement.
The FOR construct is very general, because of the lack of restrictions
on the type of initialization and loop control statements chosen. Any
or all of the three parts of the FOR may be ommitted, but the
semicolon delimiters must be present.
for (init; test; control) FOR construct
statement
example:
for (ip=strlen(str); str[ip] != 'z' && ip > 0; ip=ip-1)
;
The example demonstrates the flexibility of the FOR construct. The
FOR statement shown searches the string "str" backwards until the
character 'z' is encountered, or until the beginning of the string is
reached. Note the use of the null statement for the body of the FOR,
since everything has already been done in the FOR itself. The STRLEN
procedure is shown in a later example.
The DO construct is a special case of the FOR construct. DO is ideal
for simple array operations, and since it is implemented with the
Fortran DO statement, its use should result in particularly efficient
code.
Only INTEGER loop control expressions are permitted in the DO
statement. General expressions are permitted. The loop may run
forwards or backwards, with any step size. The value of the loop
control parameter is UNDEFINED upon exit from the loop. The body of
the DO will be executed zero times, if the initial value of the loop
control parameter satisfies the termination condition.
do lcp = initial_value, final_value [, step_size]
statement
example:
do i = 1, NPIX DO construct
a[i] = abs (a[i])
3.6 EXPRESSIONS
Every expression is characterized by a data type and a value. The
data type is fixed at compile time, but the value may be either fixed
at compile time, or calculated at run time. An expression may be a
-14-
SPP (Jan83) IRAF Subset Preprocessor Language SPP (Jan83)
constant, a string constant, an array reference, a call to a typed
procedure, or any combination of the above elements, in combination
with one or more unary or binary operators.
( Special Operators )
(arglist) procedure call
[arglist] array reference
( Unary Operators )