VAX Fortran to Fortran 77 translator

Download VAX Fortran to Fortran 77 translator

Post on 21-Jun-2016

253 views

Category:

Documents

27 download

TRANSCRIPT

  • VAX Fortran to Fortran 77 translator

    RICHARD E. HESSEL and STEPHEN B. CHICO

    Mechanical and Industrial Engineering Department, Clarkson University, Potsdam, NY 136 76, USA

    A Fortran preprocessor is described which maps VAX Fortran into standard Fortran 77. Supported extensions include long variable names, DO WHILE loops, ENDDO loop terminations, Vax Fortran tab convention, INCLUDE f'de processing, and a MODULE facility to limit the access of external programs to subprogram and common block names. The software is available in 'standard' Pascal and Software Tools Pascal form.

    INTRODUCTION

    The Fortran language is much maligned, especially by those in computer science circles, for its deficiencies compared to more modern programming languages. ~'~ We agree with these criticisms. However, as a practical matter almost all engineering software is written in Fortran. The extensive libraries of high quality mathematical software alone are a great incentive to use Fortran in our computations. 3

    While Fortran 77 made a significant step in improving the language, Fortran still suffers from many serious flaws. The next version of the language, Fortran 8x, should remove most of these flaws. 4 In the mean time we are faced with a situation similar to that of the 1970's when many compiler writers supplemented Fortran IV with extensions to overcome its deficiencies.

    Several computer vendors, for example DEC and Gould, have extended their Fortran 77 compilers. The DEC VAX Fortran is a particularly attractive version of Fortran 77. 5 The extensions it supports include long variable names, end of line comments, a general DO-WHILE loop, and an ENDDO statement to eliminate the need for statement numbers as the objects of DO loops. Also included is an IMPLICIT NONE statement which requires the type of every variable to be explicitly declared.

    Experience with this compiler has shown that use of these extensions, especially the long variable names, result in ~nuch more readable programs. However, such programs suffer from lack of portability.

    In the spirit of the multitude of Fortran IV preproces- sors, 6'7 we combined some of our old programs for detecting long variable names and translating DO-WHILE loops to produce input for the macro processor from Software Tools in Pascal by Kernighan and Plaguer a to create a new translator which maps VAX Fortran into Fortran 77.

    The features of this translator include :

    Long names: The program assumes that IMPLICIT NONE has been used (or at least that all variable names that are six characters or longer have been declared in type statements). The program will then attempt to truncate

    Accepted January 1985. Discussion closes September 1985

    names which are longer than six characters to a readable six character name. If the name cannot be shortened without conflict then a unique name is generated.

    DO loops: DO-WHILE loops of the form:

    DO WHILE (condition)

    ENDDO

    are translated into appropriate IF's and GOTO's. Conven- tional DO loops which are terminated with ENDDO's instead of a line with a statement number are translated into the legal Fortran 77 form with statement numbers.

    End of line comments: Any text which appears between an exclamation point (!) which is not in a quoted string and the end of the line is considered to be a comment. These comments are moved to the line preceding the current line as standard Fortran comments. The program understands Fortran continuation lines.

    Include statements: The source file may contain 'C$INCLUDE file' statements which are replaced by the contents of the file before any other processing is done. These statements may be nested, i.e. the included file may contain other include statements. Include statements are used to build source files comprised of many routines in separate files. Common block declarations can be stored in a file and included when needed to avoid typing errors.

    Modules: Fortran 77 supports only one level of global name. This makes it difficult to hide implementation details from users of library routines. Using this option, all global names, i.e. subprogram and common block names, are mapped into special inaccessible names except for those names which the user selects to be 'visible'.

    The writer of a 'module' would specify that certain routines or common blocks could be accessed by other routines outside of the module. All other global names would be transformed into a four letter module name and a two character sequence to form a unique six character name.

    IMPLEMENTATION OF THE TRANSLATOR The translator is implemented in Pascal. Two versions are available: one using 'standard' Pascal and one using the Pascal environment developed in ref. 8.

    The programs were written for portability with carefully isolated system dependent sections, e.g. opening flies.

    The output of the translator is fed to a general purpose macro processor to perform long variable name substitution. A suitable macro processor is 'define' from ref. 8. All of the progra~ns described in ref. 8 are available frown the publisher for a nominal charge. A 'standard' Pascal version is supplied with the translator software.

    The translator makes several passes over the program text. the passes are:

    0141-1195/85/030142-15 $2.00 142 Adv. Eng. Software, 1985, Vol. 7, No. 3 1985 CML Publications

  • Pass 1 : All C$INCLUDE file statements are replaced by the contents of the named file.

    Pass 2: The DO WHILE, ENDDO, and DO without a statement number are translated into IF's, CONTINUE's, and GOTO's. End of line comments are moved in this pass and the VAX Fortran tab convention is converted to blanks.

    Pass 3: Long variable, subprogram, and common block names are mapped into unique names. CSMODULE and CSVISIBLE statements control the visibility of global names.

    Pass 4: The define statements produced in pass 3 to drive the macro processor are merged at the beginning of the program source and are passed to the macro processor.

    Command procedures are provided to illustrate how to implement the translator on VAX/VMS and Unix operating systems.

    Detailed usage instructions may be found in the manual pages. Extensive prologue comments in the code aid in implementing the program on the users system.

    USING THE TRANSLATOR

    The module aspects of the translator are especially useful in writing large programs. The program could be broken into logical sections and written by different programmers. Each program section could access only those subprograms and common blocks of another section which had been made visible. Thus each programmer could use descriptive names for internal .subprograms and common blocks without worrying about possible conflict with other sections of the program.

    Visible names should not be longer than six characters to work properly with most Fortran compilers and linkers. Other subprogram and common block names will be processed the same way as long variable names.

    The translator requires that all variable names which are six characters in length or longer be explicitly declared. Six character names are needed to determine if a long name can safely be truncated to its first six characters. If it cannot then a unique six-letter name is generated. We recommend that all variable names be declared.

    THE PROGRAMS

    Two versions of each program are provided. One uses the Software Tools s primatives while the other is in 'standard' Pascai. The Software Tools version has been tested on VAX/VMS. The 'standard' Pascal version has been tested on VAX/VMS and Unix. Command procedures are supplied for each of these operating systems.

    A version of the define program from ref. 8 in 'standard' Pascal is included.

    A prospective user can port the primatives described in ref. 8 to his or her system and use the Software Tools version and the other tools described in ref. 8. This version is especially useful to users who already are using Software Tools.

    An alternative is to use the 'standard' Pascal versions. These programs should compile without modification on most Pascal compilers.

    The programs include extensive prologue comments w/rich describe in detail the programs. Limitations and possible extensions are enumerated.

    Sample Fortran programs are included to test the programs when they have been installed on a prospective user's computer:

    Program VF2F77 - VAX Fortran to Fortran 77 translator

    Usage VF2F77 infile outfile

    Function VF2F77 reads VAX Fortran source code and outputs

    commands for a macro processor and translated code. After being processed by a macro processor, the output is standard Fortran 77 code.

    VAX DO WHILE (condit ion). . . ENDDO and DO index = il, i2, i3 . . . ENDDO are translated.

    Text following an unquoted exclamation point (!) is moved to the preceding line as a comment.

    IMPLICIT NONE statements are changed into comments. All lower case letters not in quoted strings are mapped

    into upper case. A tab character in columns 1 through 6 causes the next

    character to logically be in column 7 if the character is alphabetic. If the character is a number other than zero (0) it is placed in column 6 to indicate a continuation line.

    All variable names greater than or equal to six characters should be declared in type statements. A list of macro processor commands will be generated to map names longer than six characters into six character names by truncation, if possible, or by generating a unique name.

    The following translator directives are supported:

    C$ INCLUDE 'filename'

    This line will be replaced by the contents of the file 'filename'. Include statements may be nested as deeply as desired.

    CSMODULE xxxx

    Marks the beginning of module xxxx. Global names (subprogram and common block names) which the user wishes to be hidden are mapped into 'hidden names' which begin with xxxx. If xxxx is no longer than four characters it will be truncated. If there is no CSMODULE directive global names will follow the same rules as variable names.

    All global names are hidden unless they appear in a CSVISIBLE statement, cSVISIBLE namel [name2. . . ] .

    The global names listed in this statement are to be unchanged by the translator. These are the global names visible to the rest of the program. As many CSVISIBLE statements as required may be used. Names on the CSVISI- BLE statement are separated by blanks, tabs, or commas.

    Bugs Underscore characters (_) are not supported in variable

    names because most macro processors do not recognize them as characters. Modifications to VF2F77 are documented if your macro processor treats them properly.

    An exclamation point in a Hollerith field, e.g. 5HBUG!, will be treated as an end of line comment indicator. Hollerith fields are not officially part of Fortran 77. 9

    Multiple common blocks are not allowed in the same COMMON statement. E.G. COMMON/BLK1/A,B,C/BLK2/ X,Y.

    Adv. Eng. Software, 1985, Vol. 7, No. 3 143

  • REFERENCES

    1 Dijkstra, E. W. How do we tell troths that might hurt?, Selected Writings on Computing: A Personal Perspective, Springer-Verlag, New York, 1982

    2 Wilson, K. G. Planning for the Future of US Scientific and Engineering Computing, CA CM 1984, 27(4)

    3 IMSL Library General Information, International Mathematical and Statistical Libraries, Inc, Houston, TX, 1983

    4 Smith, B. T. Status Report on Fortran 8x as of August 1983, SIGNUM Newsletter 1983, 18(4)

    5 VAX Fortran Reference Manual 3.0, Digital Equipment Corpora- tion, 1983

    6 Kernighan, B. W. RatJbr - A Preprocessor for a Rational Fortran, Unix Programmer's Manual, Vol. 2B, Bell Telephone Laboratories, Inc., Murray Hill, NJ, 1979

    7 Cook, A. J. and Shustek, L. J. A User's Guide to Mortran 2, Stanford Linear Accelerator Center, California 94305, 1975

    8 Kernighan, B. W. and Plauger, P. J. Software Tools in Pascal. Addison Wesley, 1981

    9 American National Standard Programming Language FORTRAN, ANSI X3.1978

    DIRECTORY OF PROGRAMS

    The first two programs are used to obtain the source and destination files, and send them through the translator programs. The actual program names used in the two driver routines will have to be modified to be compatible with the environment the translator is implemented in. For example:

    'USER1 : [C 100.STEVE.TRANS.STAND] DEFINE.EXE'

    Programs with the .PAS extension are written in 'standard' Pascal, those with the .SFT extention are designed to use the software tools primitives.

    All the following programs read from standard input and write to standard output :

    VF2F77.COM-VAX/VMS command procedure used to run the translator programs.

    UNIX .SCR-Un ix shell script to run the translator pro- grams.

    INCLUDE.PAS-Used to include external files into the main source code. Note: Pascal File 1/O is system dependent and may have to be modified, currently set up for VAX/VMS operating system.

    WH2STD.PAS-Converts non-standard do loops into a form compatible with standard FORTRAN 77, plus processes end of line comments, VAX tab conventions, and maps text not in quotes to upper case.

    LONGNM.PAS- Creates a list of define statements to redefine long variable names. The list should be affixed to the beginning of the output from WH2STD.PAS for use with the define program.

    DEF INE.PAS-Reads from standard input and replaces every occurrence of 'str l ' with 'str2' following the define command: define(strl , str2).

    The following programs perform the same functions as those above, but are designed to work in the software tools environment:

    INCLUDE.SFT WH2STD.SFT LONGNM.SFT DEFINE.SFT

    The next programs are used as test programs. TEST.F is the source, MATADD.SUB, and MATMULT.SUB are separate subroutines that are included with the include program:

    TEST .F - Main program that calls MATADD.SUB and MATMULT.SUB.

    MATADD.SUB - Subroutine that adds two matricies together.

    MATMULT.SUB - Subroutine that multiples two matricies together.

    XX .OUT-The translated output from the three test programs.

    VF2F77.COM VAX/VMS command procedure to run translator programs

    $ ~ VAX/VMS comand procedure to dr,ve tile translat,~! $ ! The source code is passed through the followin~ l,rogram~ $ ! include -- includes external source files. $ I wh2std -- translates while loops $ I longnm -- processes long variable names $ [ define -- processes the define statements generaL~,d by Iongnm $ t $ ! clear the directory of possible conflicting file:~ $ if fSsearch("temp*.txq;*") .nes. "" then $ delet!, lemp*.tKq; ~ $ ~ $ I get input and output fires $ infile =~ pl $ outfile ~= p2 $ if infile .eqs. "" then $ inquire inlile "source ~le" $ if outfile .eqs. "" then $ inquire outfile "output file" $ ~ $ ! if an output file is not mpecified then the output will $ ! go to ~tandard output and no output file will be saved $ ~ $ ! connect standard input and output to the appropriate files $ assign/user_mode "infile" sys$input [ input file spec $ as~ign/umer_mode templ.txq sys$output [ output from include $ run userl : IclO0.~teve.trans.stand] include .exe $ ~ $ assign/umer._~ode templ.txq sys$input [ output from include $ assign/u~er_mode temp2.txq sys$output [ output from wh2std $ run userl:[cl00.steve.trans.stand]wh2std.exe $ ~ $ delete te~p.~l.~txq;* $ ~ $ assign/u~er_mode temp2.txq sys$input I Output from while $ assign/user_mode temp3.txq sys$output I output from flung $ run userl : [cl00.steve.trans.stand] longnm.exe $ ~ $ I append the result of wh2std to the define table $ ~ check if there was shy output from the long name program $ ~ $ if fSsearch("temp3.txq;*") .eqs. ~'" then goto lablel $ append temp2.txq temp3.txq $ assign/user temp3.txq sys$input S goto fable2 $1ablel: $ assign/user_mode temp2.txq sys$input $1able2: $ if outfile .nes. "" then guru fable3 $ des ssign sys$output $ guru fable4 $1able3: $ assign/user "outfile" sys$output $1able4: $ run [clO0.steve.trans.stamd]define.exe $ t $ I delete the work files $ delete te~p*.txq;*

    UNIX.SCR Unix shell script to run the translator programs

    ~ Transf77 - shell script to run the programs ~ necessary to t rans la te VAX/V~L~ FORTRAN into # s tandard For t ran 77 # # useage: tran~f77 infile.f outfile.f # # process includes and p ipe to "twhile" include txqpl # # create list of defines in txpq2 longnm < txqpl > txqp2 # # put list of defines on top of output from "twhile" # and pipe to the "define" program cat txqp2 txqpl I define >$2 # ~ remove temporary files rm txqpl rm txqp2

    144 Adv. Eng. Software, 1985, Vol. 7, No. 3

  • INCLUDE.SFT Copies external files into the main file

    INCLUDE PROGRAM(aft ) include -- replace c$include "file" by contents of file input is from standard input. output is to standard output. Both input and output are redirected to be the appropriate files This version is designed to run in the Software tools environment. The file l/O is isolated in "include" and "finclude"

    REFERENCE Kernighan & Plauger, "Software Tools in Pascal " 198! Addison-Wesley Publishing Company, Reading, HA

    ( wrapper (CU) -- this is the wrapper for all the software tools { Rename this ~ile "name.pan", where name is the name of the tool. { For example: rename it f i lter.pan ( This next li~e inherits all the global definitions that go along { _ with the software tools. [inherit('userl:[bllb.softtool.environ]globdefs.env')]

    program wrapped(input,output); { Include your program here. For example: ~incIude "filter.prc" )

    { include -- replace c$include "file" by contents of file }

    procedure inc lude ; vat

    incl : string; { value is "cSinclude ~

    { lower - - re turn "a" in l ower case } FUNCTION lower( a : CRARACTER ) : C l inChER; { return~ ~ in lower ca~e } { a~mae~ difference between upper & lower cmse xs a constant } VAR ch : character ; Begin { lower}

    if a i~ [o rd( 'A ' ) . .o rd ( 'Z ' ) ] then ch :ffi a + ord('a') - ord('A') e lse ch :" a;

    lower := ch ; End; {lower)

    { equal -- test two strings for equality } { modif ied to eeg leet case of the strings ) function equal (vat strl, sir2 : string) : boolean; vat

    i : integer; begin

    i : - 1; while ( lower (s t r l [ i ] ) = lower(str2[i])) and (strl[i] ENDSTR) do

    i := i + i; equal :~ (lower(strl[i]) - lower(stri[i]))

    end;

    { finclude -- includes the file desc f }

    procedure f~nclude ( f : f i l edesc) ; vat

    line, sir : string; loc, i : integer; fl : filedesc;

    { getword -- get word rom s[i] into out ) function getword (vat s : string; i : integer;

    vat out : string) : integer; vat

    j : integer; begin

    while (sli] in [BLANK, TAg, NEWLINE~) do i := i + i;

    j :~ 1; while (not (s[i] in [ENDSTR,BLANK,TAB,NEWLINE])) do begin

    out [ j ] := s [ i ] ; i :~ i + i; j := j + 1

    end; out [ j ] := ENDSTR; if (~[i] - ENDSTR) then

    getword :- 0 else

    getword := i end ; begin

    while (getline(line, f, MAXSTR)) do begin foe :~ getword(line, l, s i r ) ; if (not equa l (a r t , inc l ) ) then

    puts t r~ l ine , STDO~T) e lse beg in

    loc := getword( [ ine , Ioc , s i r ) ; str[length(str)] := ENDSTR; { remove quotes } for i :- I to length(sir) do

    str[i] := str[i+l]; fl := mustopen(str, IOREAD); finclude(fl); closef(fl)

    end end

    end; begin

    { sets t r ing( inc l , "c$ inc lude ' ) ; inc l [ l ] := ord( ' c ' ) ; inc l [2 ] := ord( '$ ' ) ; incl[31 := ord( ' i ' ) ; inc l [4 ] := ord( 'n ' ) ; inc l [5 ] := ord( ' c ' ) ; inc l [6 ] := ord( ' l ' ) ; inc l [7 ] : " o rd ( 'u ' ) ; inc l [8 ] := ord( 'd ' ) ;

    incl[gJ := ord('e'); incl[10] :" ENDSTR;

    finclude(STDIN) end; begin { wrapper }

    iaitio; { Call program here. For example: filter } include

    end. { wrapper }

    WH2STD.SFT Processes nonstandard do loops, etc.

    W~I2STD PROGRAM (sft) Program Overview

    This program is used to convert some of the nice features of VAX FORTRAN into a form compatible with standard FORTRAN 77

    The particular features handled in this program are: DOWHILE (cond i t ion i s t rue)

    : b lock o f s ta tements

    : ENDDO

    DO index vat = lower ,upper ,s tep :

    b lock o f s ta tements :

    ENDDO

    VAX tab convent ions wh ich i s a tab in the i r s t 6 co lumns fo l lowed by a d ig i t ( I . .9 ) i s a cont inuat ion o f the prev ious l ine . I t i s p rocessed in to : 5 b lanks , the d ig i t ,TARS[ZE-6 b lanks , and the text

    End o f l ine comments a re s ign i f ied by an " ! " . The text between the "~" and the end o f the l ine i s a comment . I t i s p rocessed in to a normal Comment and p laced be fore i t s l ine o f o r ig in

    IMPLICIT NONE s ta tements a re commented out . Th is i s fo r use w i th the Iongname program.

    There are two run t ime opt ions ava i lab le to the user imp lemented as comment cards in the source code . Spaces are not a l lowed in the opt ion key words .

    cSUPPER t rue - -> maps a l l tex t not in quotes to upper ease . f lase - -> does not change case . Defau l t = t rue .

    C$DEBUG t rue - -> outputs d iagnost i cs to s tandard output . fa l se - -> no d iagnost i cs a re output . Defau l t ~ fa l se .

    Use: cSUPPER fa l se

    F low o f the P rogram

    A buf fe r i s f i l l ed w i th a l l the text necessary to obta in a complete FORTRAN s ta tement inc lud ing a l l cont inued l ines and any b lank l ines o r comments that a re in terspersed in the code . Th is i s where the end o f l ine comments and tab convent ions a re processed out

    F rom th is bu f fe r a s t r ing "s tmt . tt" i s obta ine~. Th is s t r ing conta ins a l l the re levant FORTRAN te~t of the ent i re s ta tement . This string is formed so that the procedures testing the statement do not have to know about column structure or continued lines.

    If a nonstandard "DO" structure is found then the buffer is processed (by the procedure "pr_do") as follows:

    The "DO WNILE" statements are mapped into 3 lines:

    IF( .NOT." & (original "DOWRILE" argument)" -- Remains the same & )into xxxxx -- Is added to the end of the stmt.

    The DO/ENDDO loops are maped into:

    DO xxxxx" & ..... rest of the original "DO"

    Note: The statements are broken up to prevent them from being pushed past column 72 when the additional characters are added.

    Nested "DO" structures are processed recursivly.

    The procedure "pr_do" repe~ts the process of getting a statement and testing it for do types until it finds an "ENDDO". If another nonstandard do structure is found while looking for the "ENDDO" "pr_do" then recursivly calls its self to process the new found do structure

    When an "RNDDO" is found it is processed as follows:

    When associated with a "DOkrHILE '' the keyword "ENDDO" is mapped into 2 lines:

    GOTO yyyyy" "xxxxx CONTINUE"

    For a DO / ENDDO loop the "ENDDO" is maped into:

    "xxxxx CONTINUE"

    For both cases if the "ENDDO" is labeled a continue statement with the original label is inserted before either of the two above enddo cases are processed.

    Adv. Eng. Software, 1985, Vol. 7, No. 3 14$

  • PROGKAM STRUCTURE: - - kndentat io [~ :n~tcates iev , , J c,t nes tkng

    PROGRAM wh2stC main rout ine ~DN. lower re turns a char : I c ies t il l 1 ~wt t~tse I 'RO. p r vatab - - R iOt , s> vax t ~b ( ( )nv , ' i [ 1o12 FUN. rea l s t ru t d , t , imln :~ i f s~ l i rw i ;t rea l s tml .

    FUN. a l l b lanks a l ! b lank lane t rm~; PRO. f lush buf fe r dumps but le r COllt( ' I [ s to "dest ln"

    PRO. change case - changes text to cap i to l le t te l ~ PRO. put_ in buf f - puts a l ine in the buf fe r

    PRO. s t r ipcom takes o f f end o f l ine comments PRO. dumpexcess - - dnmps excess comments

    PRO. pr opt ion - - p rocesses opt ion comment cards FUN. f ind t rue - - .-> t rue i f " t rue" lo l lows t i l e opt i{~n

    PRO. f i l l bu f f - - f i l l s bu f f w i th ent i re s ta tement PRO. i s cont inued - determtns i f the l ine ts cont .

    PRO. in i t ia l i ze - - in i t ia l i zes s t r ings and f i l es PRO. get s tmt - - gets a FORT~N s ta tement f rom the buf fe r .

    FUN. beg in ing_o f text - - -> pos o f 1s t cDar . o f l~e PRO. get_ tx t - - gets re levant fo r t ran s tmt . text

    PRO. pr st :mr - p rocesses a s ta tement FUN. f ind do_ type - - l tnds the type o f do => do type

    FNR. ~s~enddo - - z l s t ru t , i s an enddo => t rue FUN. i s dowh~le - - t f s tmt . i s a dowhi le -> ~rue FUN. do . loop_type . . . . > do type FUN. f ind rparen - - => r ight parenthes is poskt ion

    PRO. pr do - - p rocesses a do s ta tement PRO. inser t - - inser ts a l ine in the buf fe r FHN. f~nddo~os - => buf fe r l ine w i th do s ta tment PRO. cb to s i r conver ts in teger knto a cbr s t r ing FUN. has_a number i f s tmt . i s laae led -> t rue PRO. pr_dowhi le - p rocesses a dowhi le s ta tement PRO. pr_do nn processes a do w i thout a labe l PRO. pr enddo - - p rocesses an enddo s ta tement

    PRO. h lde_~mp_none - - comments out imp l i cz t none s t ru t .

    * **~********** NOTES : ************

    THe program knows noth ing o f Ho lor i th i i e ld and wou ld cons ider an "~" in such a f ie ld as an end o f f ine co~e~t . I t wou ld a l so change the case o f le t te rs in a t to le r t th fo rmat ~f the change case mode i s ac t iw , .

    An exc lamat ion mark ~n a quoted ~tr tng ks xgnored as an end o f l ine co~ent marker

    Spaces in the "DO WHILE" and the "END DO" s ta tement a re lega l . The words tDemse lves can not be cont inued, but the res t o f the s ta tement can be sp l~t as des i red .

    On ly s ing le quotes mark a q .o ted s t r ing .

    The on ly [ i i~( normal text i s changer a round i s wHeu there a~e a lo t o f comments . In o rder Io p revent bu l le t over f low they are dumped out sav ing on ly the rea l s ta tement l ines in the buf fe r . ( see prncedure "dump ex ;ogs" in "put in bu l l " )

    Under scorees ar{ ~ used througbt tbc ,od( to l l : tHr~vt' readkb l lk t> Under scores are m~[ s tandard tasca l sc i f y.)u~ (ompi le r do~,s lkOt aupor t th ie i use they can b ' /e l ( t tA ~ l lh ] t i l t , r ~r s~l: ca l l [ t i t

    TDe program usps the pr la /a t i res ann cbarecte : s+,t d#~w' loped an "Sof twaro Too ls ~n Pasca l " By Kern ighan and P lauger .

    Dkck Hanse l January 8 , 1983 rewr i t ten w i th extent ton8 by Steve Oh[co Foburary 19~

    { wrapper (CU) - - th i s zs the wrapper fo r a l l t l~e so i tware too ls { Th is next l ine ~nher i t s a l l the g loba l de f in i t i{ms that go a long { with the so f tware tools . { ~nherit ('user i : [bl lb. soft tool .env i ron lg lobdef s .env')]

    PROGRAM wrapper{ input ,out put) ;

    PROCEHURE wh~le! 77 ;

    CDNST { co lumn coustants }

    COL I - 1 ; CDL 11 - 1 i ; COL 2 - 2 ; COL 12 - 12 ; COL 3 - 3 ; COL 13 - 13 ; COL 4 - 4; COL 14 14; COL 5 - 5; COL 1 5 - 15 ; (;Ol. 6 = 6 ; COL 16 - 16 ; COL 7 - 7; COl, 17 - 17 ; (OL 8 8; COL 18 = IR ; COL 9 - 9; COL 19 "- 19 ; COh l0 i0; COL 20 20; COL 72 - 72 ;

    TABSIZE = 8; STARTING L INE RUM - lO000; { s1~r~ ins number fo r c reated s tmts . CONTINUE CHAR - AMPER; { "&" } MAX STMT LENGTH - 1320; { 20 l ines x 66 char / l in< } MAX BUfF LENGTH - 100; { buf fe r can ho ld I00 l ines ot text } BUFF PROTECT 95; { prevents over f low o f the buf fe r }

    VAR

    t buff line = I . .MAXBUFF_LENGTI I ; t_text - ARRAY [ I . .MAR STMT LENGTH] OF CRARACTER~ t strut - RECORD

    tx t : t text ; { ac tua l text u : the ~tatem~nt ) tx t__ len : i . .~4a.ST~r LENGTH; { length ot s ta tement text

    END; { s tmt record } t o f _do (DOWRILE ,DO NN,ENDDO,NORM DO,N{ 7)~),

    le t : in teger ; { k~eps t r~ck o f ~* o: ] ln , , s in s tm~ } l~ne f lag : boo lean; { inH icates end o l f i i e when ta l s~ ) l ine hum : in teger ; { l ine number (c reated a.~ program) )

    buf fer : a r ray I l . .MAX BUFF_LENGTR] of STRING; buff ct : integer~ {keeps track of the # of ]ini!s zn the bur fo r )

    { STR ING constanLs ~ CAP_C : CHARACTER; dowH, scontznue , s , fnot , sgoto ,send : STR!NG; l ine : STR ING;

    s tmt : t _s tmt ; DEBUG : boo lean; case_ f lag : boo lean; { t rue => a l l upper : fa l se -> don ' t change} ten : a r ray[O. .4 ] o f in teger ; { powers o f 10 } source : F1LEDESC; { o r ig ina l vax source code w i th "wh i les" } de~t in : F ILEDESC; {"wh i le loops" rep laced w i th s tandard f77 code}

    {1 **** lower ****} FUNCTION lower{ a : CHARACTER ) : CHARACTER; { re turns a in lower case } ( assumes d i f fe rence between upper & lower case i s a cunstant } VAR ch : character ; Beg in { lower}

    i f a tn [o rd( 'A ' ) . .o rd ( 'Z ' ) ] then ch : - a + ord( 'a ' ) - o rd ( 'A* ) e l se ch := a ;

    lower : - oh ; End; { lower}

    { 1 ********* pr_vaxtab ********* } { processes l ines cont inued w i th vax TAB convent ions } { uses the or ig ina l tab character and rep laces the f i r s t tab } { w i th the number o f spaces needed to put the f i r s t character } { in co lumn 7, o r co lumn 6 i f i t i s a cont inu ion l ine } PROCEDURE prvaxtab(VAR l ine : STR ING}; VAR t_ l ine : STR ING;

    j , k : in teger ; v tc : in teger ; { vax tab cont inuat ion o fset } tabpos : in teger ; { tab pos i t ion }

    Beg in { prvaxtab } j :=0; tabpos := 0 ; { i f a comment l ine then gore end and re turn } i f not ( l ine[COL 1] in [CAP C ,LETC,STARI ) then beg~n

    repeat j := j+t ; i f l i ne [ j ] - TAB then tabpos : - j ;

    unt i l ( tabpos 0) o r ( j >- COl, 6 ) ;

    i f tabpos > 0 then beg in fo r j : 1 to ( tabpos 1) do t l ine i J ] : l i ne [ l ] ;

    ~f I ine[ tabpos+l} in [o rd(* l ' ) . .o rd ( '9" )} tDen v tc : - 1 e l se v tc : - 0 ;

    fo r j : - tabpos to (COl + v tc ) H~, t l inv [ i l : B I~NK; j : - (COl, 6 v tc ) ; k : - tabpos ; repeat

    ~ := j+ l ;

    k := k+i ; t _ l ine[ j ] := l ine[k ! ;

    unt i l { l ine[k ] = ENDSTR) o r (k >= MAXSTR); l~ne : - t _ l~ne;

    end; { i f tabpos > 0 } end; { i f .o f a comment }

    End; { pr_v~tab }

    { 1 ****** rea l s tmt ******* } FUNCTION rea l _s tmt( l ine : STRING) : boo lean; VAR rs : boo lean;

    { 2 ****** a l l b lanks ******* } FUNCTION a l l b~anks(VAR l~ne : STRING) : boo lean; VAR i : in teger ;

    Hi : boo lean; { a l l b lanks f lag } Beg in

    i : - 0 ; b f := t rue ; repeat

    i : - ; + 1 ; i f not ( l ine[ i ] in [B I&NK,TAB,NEWLINE,ENDSTR] ) t i l en

    b f : fa l se ; unt i l ( b f = fa l se ) o r ( l~ne[ i ] = ENDSTR) ; a l l b lanks : - b f ;

    End; { a l l b lanks }

    Beg in { rea l s tmt } i f ( ( i inT [ i ] in taTAR,CAP C , le tc ] ) OR a f I _b lanks( l ine) ) then

    rs := fa l se e l se rs : - t rue ; rea l s tmt := I S ;

    End; { Tea l s tmt }

    { 1 ********* f lush_buf f ************** } PROCEDURE f lush ._buf fe r ; VAR i , j : in teger ;

    l ine : STR ING;

    { 2 ******** changeca~e ******** } PROCEDURE change_case(vat l~ne : STR ING}; { changes a l l l ower case le t te rs to upper case ~f they are not } { quotes . Assumes that the d i f fe rence Between upper and lower case } { ~s a constant } VAR i : in teger ;

    ,nquote : boo lean; Beg in { change case }

    inquote : fa l se ; i :- 0; repeat

    i : - i + i ; i f 1 ~ne[ i ] - SQUOTE then knquote : - not :nquote ; i f ( l ine [ i ] in [o rd( 'a ' ) . .o rd ( ' z~}] ) and (not inquote) then

    I ine[ i l := ] ine[ i ] + (o rd( 'A ' ) {~rd(*a ' ) )

    146 Adv. Eng. Software, 1985, Vol. 7, No. 3

  • until line[i] = ENDSTR; End; { cbangecase }

    Begin

    for i := I to buff ct do begin if case_flag then change_case(buffer[it); putstr(buffer[i],destin);

    end; { for i } buff_ct := O;

    End; { flush_buffer }

    ( 1 ********* put_xn_buff ************** } { puts the llne in the buffer after striping off the end of { line comment and puling it in the buffer first PROCEDURE put_in_bnff(VAR line : STRING ); VAR i : integer;

    { 2 ******** strip_tom ********* } PROCEDURE strip_com(VAR line : STRING); { used to convert end of line co~ents to standard form } { Also used to test if the length of non-comment lines is 72 } V~dR inquote : boolean;

    endline : integer; i,j : integer; comstr : STRING;

    Begin { strip_tom } i := I; inquote :ffi false; while (i COL_72) and { subtract 2 for NEWLINE and ENDSTR (not (l ine[COL l] in [CAP-C,LETC,STAR])) then begin

    message('>>>>>>> ERROR

  • dowh[ l ] := ord( 'e ' ) ; dowh[8} :~ ENDSTR;

    scont lnue[ l ] scont tnue[2] scont tnue[3] scont~nue[4] scont~nue[5] scont~nue[6] scontznue[7] scont tnue[8 /

    s i fnot[7] := ord( 'T ' ) ; s i fnot[8] := ord( ' . ' ) ;

    := ord( 'C ' ) ; sgoto[ l ] := ord( 'G ' ) ; :- ord( 'O' ) ; sgoto[2] :- ord( 'O ' ) ; :- ord( 'N ' ) ; sgoto[3] :- ord( 'T ' ) ; := ord( 'T ' ) ; sgotoI4] :- ord( 'O*) ; := ord( ' I ' ) ; := ord( 'N~) ; send[ l ] : - o rd (~e ' ) ; : - o rd ( 'U ' ) ; send{2[ : - o rd ( 'n ' ) ; := ord( 'E ' ) ; send{3[ : - o rd ( 'd ' ) ;

    send[4] := ord( 'd ' ) ; send[5[ := ord( 'o ' ) ; send[6[ := ENDSTR;

    { start img va lue of s tatement numbers } l ine_hum := STARTING LINE NUM;

    { powers of I0 } ten{O[ :~ 1; fo r j := 1 to 4 do ten{ j [ : - te~[ j - l l * I0 ;

    source := STDIN; { so f t too ls constants } dest in := STDOUT;

    case flag := true; DEBUG := false;

    { get the str ing " l~ne " for ti l l bull ] l ine_f lag := get l ine ( l ine ,source ,MAXSTR) ; if l ine_f lag then pr_vaxtab( l ine ) ;

    End; { in i t ia l ize}

    {l **~****** get_s tmt *********~ } FUNCTION get_stmt( VAR stmt : t stmt ) :boulean; { Gets ent i re fo r t ran statement, inc lud ing cont inued lines, Into { s tmt . text [ . . ] and the l ine nnmber i f any i s s to red ~nto { s t ru t .hum[ . . ] } VAR

    1,be : in teger ;

    { 2 *~***** beg in ing o t_ text *** ' **~* } { f inds the pos i t ion o f the f i r s t character of ~he actua l { s ta tement text , ~gnor ing b lanks , tabs , :md s ta tement labe ls FUNCTION beg in ingo i text ( l ine : STRING) : in teger ;

    VAR j , i : i n teger ;

    Beg in { heg in ing~of text } i :~ COL 1; { in the f i r s t s ix co lumns then can be a number , b lank , o r a tab wh i le ( i

  • find_do_type := temp_do; end; { with )

    if DEBUG then writeln(~find_do_type: temp_do = ~,temp_do); End; ( f inddo_type }

    { 2 ********** pr_do ************ } PROCEDURE pr_do(VAR stmt : t_stmt; do_type : t_of_do); { process a "do" statement } TYPE num_str = array[1..5) of character;

    VAR i,j : integer; { counter and loop indicia } slinel : nu~st r ; { line number string xxxxx if(.not } aline2 : hum_sir; { line number string "guru yyyyy" } curt_do : t_of_do; do~os i t ion : t buff line; { buffer position of do stmt. }

    { 3 ****** insert ******** } { the STRING instr is inserted into the buffer in front of b~os} PROCEDURE insert( instr : STRING; VAR b~os : integer); VAR i,j : integer; Begin ( insert )

    for i := buff ct + i downto b_.pos + I do buffs=l iT := buffer[i-l);

    bu f fe r [b~s] := instr; buff_ct := buff_ct + I; b~pos := b~os + i;

    End; { insert }

    { 3 ****** f ind the do ******* } { a do statement is always the first non BLANK or } { non cogent line in a the buffer FUNCTION find the do : t buff line; VAR i : t buff line; Begin

    i := 0; repeat

    i := i + I; until real_star(buffer[i]) find the do :~ i;

    End; { find the do }

    { 3 ****** ch to s t r ****** PROCEDURE ch tO s t r (n : integer; VAR s t r num_st r ) ; { t rans la tes in teger n into 5 char s t r ing s t r} VAR j : integer;

    Begin { ch_to_s t r } fo r j :- 1 to 4 DO

    s t r [6 - j l := ord('O') + (n mod ten[ j ] - n mod ten[ j - l ] ) div ten[ j - l ]

    s t r [ l ] := ord( '0" ) + (n - n mod ten[4] ) d iv ten[4] ; End; ( ch_to_str }

    { 3 ******* has_a_number *******} FUNCTION has ._a . _~ber (line : STRING) : boolean; { determins if there is an existing statement label for the { statement } VAR j : integer;

    nu~ex is t : boolean; Begin { has_a_number }

    j :E COL 5; { last legal column for a statement label } hum_exist := false;

    repeat if line[j] IN [ord('l ')..ord('9")] then

    mum_exist : - true { must be non 0 } else j : - j - I ;

    until (j = O) or (hum_exist); has. a_number :~ num._exist ;

    if DEBUG then writeln('has_a_number:' , num._exist); End; {has_a._number)

    { 3 ********* pr_dowhile *********** } PROCEDURE pr_dowhile(VAR do_pos : t buff line); V~R addst r : STRING;

    i,j : integer; e~os : integer; { position of the e in "dowhile" ) last_real : integer;

    Begin { put in line number - use existing number if it is there }

    if has_a_n~ber(buffer[do_pos]) then begin j := I; for i := COL_I to COL 5 do

    if buf fer ldo~os, i ] in [o rd ( '0" ) . .o rd ( '9" ) ] then begin

    s l ine l [ j ] := buf fe r [do__Dos, i] ; j := j + l ;

    end; for i :2 j to COL_5 do slinel[i] := BLANK;

    end e lse begin

    ch to str(l ine_num,slinel); l ine_hum := line_hum + I;

    end;

    { pot in if(.not." } { pos i t ions 12345678901234 }

    for i : - COL 1 to C0~_5 do addscr [ i ] := s l ine l [ i ] ; addstr [COL_6~ : - BLANK; for i : - COL 7 to COL 1~ do addst r [ i ] : - s i fnot [ i -6 ] ; addst r [COL_ l~) : " REWLINE; addstr[COL 16] : - ENDSTR; inser t (addst r ,do~os) ;

    { delete the "dowhile" and make the line a continuation of } { the "if(.not." }

    i := O;

    repeat i := i l ;

    until lower(buffer[do.us,t)) = LETE; e~os := i; { posit ion of the "e" in the dowbile } for i := COL I to COL_5 do addstr[il := BLANK; addstr[COL 6T := CONTINUE_CHAR; addstr[COL 7] := BLANK; j := e~os ; i := 7; repeat

    i :- i+l; j := j+l ; addstr[i] := buf fer [do.us , j ) ;

    until (buffer[do_Dos,j) = EHDSTR); buffer[do__pos] :- addstr;

    get 2nd line number, for the trailing guru ) on the "if(.not ..... " } ch_ to_s t r ( l ine_~, aline2); llne._num :E line_~um + l;

    build addstr to be " & )GOTO xxxxx" ) addstr positions are 123456789012345678 }

    for i :- COL l to COL_5 do addstr[ i) := BLANK; addstr[COL_6~ := CONTINUE_CHAR; addstr[COL_7] := BLANK; addstr[COL 8] := RPAREN;; for i :" COL 9 TO COL_S2 do addstr[i] :- sgoto[i-8]; addstr[COL_l~] := BLANK; for i := COL 14 to COL_18 do addstr[i] := sline2[i-13]; addst r [COL l 9] := NEWLINE; addst r [COL20] := ENDSTR;

    the position to insert the return guru after the ) last real line in the buffer } for i :- I to buff ct do

    if ~ea1_atmt(b~ffer[i]) then last_real := i; last real :- last real + l; _ -- i nser t (addst r , las t rea l ) ;

    End; ( p r_dowhi le )

    { 3 *********** pr_do_nn ************** } PROCEDURE pr_do_nn(A~ do_poe : t buf f l i ne ) ; ~ addst r : STRING;

    i , j : i n teger ; o_pos : in teger ; ( pos i t ion of the o in the "do" )

    Begin i f has_a_number(buf fer [do ._pos] ) then beg in

    j : - 1; for i :" COL~I to COL 5 do

    if buffer[do_pos,i~ in [ord('0")..ord('9")] then beg in

    addstr[j] :- buffer[do_pos,i]; j := j +1;

    end; fo r i := j to COL_6 do addst r [ i ] : - BLANK;

    end e l se beg in

    for i :- COL_I to COL_6 do addst r [ i ] := BLANK; end;

    addstr[COL_7) := ord( 'D ' ) ; addstr[COL_8] := ord( 'O ' ) ; addstr[COL_9] : - BLANK;

    { now get the number to make a normal do loop ) ch . _ to_s t r ( l lne_a~m, s l inn2) ; I tue._num : " line_num+l ;

    fo r i := COL l0 to COL~14 do addst r [ i ] : " s l ine2[ i -9 ] ; addatr[COL_l~] :- NEWLINE; addstr[COL_16] := ENDSTR; i nser t (addst r ,do~os) ;

    { now de le te the "do" from the or ig ina l l i ne } { and make the original a continued line }

    i := O; repeat

    i := i+l; until ( lower(buffer[do_pus,i)) - LETO); o._pos := i; { position of "o" in do } for i :2 COL I to COL_5 do addstr[i] := BLANK; addstr[COL 6T := CONTINUE_C~AR; addstr[COL 7] := BLANK; j := o_pos; i := 7; repeat

    i : - i+l; j : - j+l; addst r [ i ] := buf fe r [do_pos , j ] ;

    unt i l (bu f fe r [do_pos . j ] = ENDSTR); i f i > co1_72 then beg in

    puts t r (bu f fe r [do__pos] ,a tder r ) ; measage( 'S t r lug longer then 72 a f te r be ing processed ' ) ; e r ro r ( 'p robab ly a tab ( l char . ) changed to 5 b lanks ' ) ;

    end; buffe~[do_pos] :" addstr;

    End; { pr_do_nn }

    { 3 ********* pr_enddo *********** } PROCEDURE pr_enddo(s l ine l , s l ine2 : num._sir); { p r in ts rep lacement fo r "ENDDO" l ine assoc ia ted w i th a "WHILE" } VAR j : i n teger ;

    end_pos : t _bu f f _ l ine ; l_temp : STRING;

    Eegin { pr_enddo } i f DEBU~ then wr i te ln ( 'p r_enddo: cur r_do- " ,cur r . _do) ;

    Adv. Eng. Software, 1985, Vol. 7, No. 3 |~9

  • end jos := t tnd . . the_do;

    ( i t the enddo l ine has a number Lben tur i : at i' ( in to ##### cont lnue /

    i f ha~ a numbt . r (bu[ f t . r [ t .nd~o~)) lht ' t , ~, ' ,1, : _ . j l ; fo r t : - DOt 1 to COl $ do

    i t bu f l , . r [en : i~o~, i~ I n [o rd( 'O ' J , .o td ( '9" ) l :hen begin

    l._temp[ II : = but fer Eend po~, ~ ] ; j : - j + 1;

    end ; ~or i : " j to COL_6 do 1 . t t .mp[*] := BLANK; fo r l := COL 7 to COL_I4 do _ t t .=p[* ] : - ~ont : , :u t , [ t -h{ , l _ temp[COL 15l := NEWI.1NE; l _ temp[COL 16] : - ENDSTR; n~er t ( l _ t emp ,end_po ~) ;

    end ;

    t f cur t_do * I~)WHILE then begxm wr~te gore yyyyy , fo r j := COL I to COL 6 do ] f iemp[ j{ ~ BIANK; /o r j :~ COL Y to COL 10 dc i__r~mp[j', : - ~goto( l -~ , ] ; l _ temp[COL 11{ ; - BINK; ~or j := C'~l. 17 t~ COL !~ ~ I : , 'mp~i :" , , l l n , . l{ I l l~ ; I_Lemp{COL 17] := NEWI. INE, l . . temp[COL 18] :~ ENDSTR; { have to ~h i l t the i ln , ' s ,:; tt~, bu : : , .~ It, u:,,K,, r, om { lo t th , ' t ' x t la l lnv l t l~ . r t{ i :,.ml,,c*~a pos) ,

    vnd , { :~ cur t_de - :R)WHIIV : : ,~ ; ,

    wr i te xxxxx cent :nun , t i l l s IS don,' :o r both ~vl,*'~ o: t, ncdo . .

    fo r j := COl. I to COL 5 do I temp[ ]} : - ~ , l lne2[ J ] ; l _ temp[COL 6J := B~NK; to t j : - COL ? to COL 14 do l _ lemp[ j [ := ~cont~nue[ j -b ] ;

    I _ te=p[CO1. 15] : - NEWI.INE; l ._temp[COl. 16] : - ENDSTR; { rep lace enddo w i th I temp } bu l le t [end post : - !. l eap ; { de le te~; tb, . "ENDIgV'

    f lush_bur le t ; End; { pr_enddo }

    Be~xn { pr._do } t :ur r _do : : do_ type; do3ost t lon : " i ind ._ the _d~, t f DEB~ Lhen wr t te ln ( 'p r do: do . typer ' ,vur r , do~;

    11 do_type - ~WHI I .E then beg in pr dowln le (do_ pos ~t /on} ; f lush _bur [~'r ;

    ,,nd

    t , l~e 1: do_ type = ~_NN then b,-gll: p r_do_tm{ do_ po~ i t i on) ; f lush buf fe r ;

    , 'nd ;

    { look io r the "end do" } repemt

    i ! get_s t ru t (s t ru t ) then bt .g lu do type : = t lnd_do , type ; i [ do_ type " EBD~ then pr .enddo(s l ine l ,~ l tne2) e l se i f do_ type n [~ NN,dowhi le ] then pr_dn(~tmt ,do_ type) e l *e [ lu~h_ buf fe r ;

    etld e l se

    er ror ( 'mt*s~ng cnddo to m~tck prev lmts "do ~t rut tures" " ) ; unt i l (do_ type - END~) ;

    End; { pr_do }

    Beg in { pr_s tmt ~ do. typv := l itld do_ type; 1~ do type in [DO. .NN.dowbl le] thvn pr do(s to t ,do typ, . ' . v l se f lush_b~l le t i

    gt~d, { pr ~tx l ?

    I * *** whi le I ; / ***~ BeRzu {whz le f / l )

    ~nxt ~a lzze ;

    iepea I L ine_ f lag : - get s t~t (s t : : t ) . I f l i ne . f l~g (h l .n p~_~tmt(s tmt) ,

    unt i l ( l~ne . f lag - 1~1~};

    End , {whi le177)

    Beg in { wrapper )

    lnz t io ;

    ~hz le t?? gnO. { ~rapper ~

    LONGNM.SFT Creates a list of define statements for long variable names

    LONGNM PROGRAM (s f t ) } P rogre~ to ! rod var iab le names longer than 6 characters in FORTI~N )

    dec la ra t ion s ta tements and determine a un ique h character name to } be u~ed im p lace ot the long name. }

    }

    The un ique ~me xs e i ther a t runcated vers ion of th , ' or ig ina l name } or t f t runcat ion cause~ a conf l i c t with an ex~ttng name, a new un ique} name i~ generated . Tile l x ra t four characters o f the g~nerated name can} be spec i f ied by the user with a CSUNIQUE opt ion :a rd . The defau l t fez the pre f ix x~ "UNIQ'*. Tile remain ing twu Lharacters a re det t . tmtn'd by the order that the name~ are generated ; s ta r t ing at O0 and end in~ at

    ZZ. ThLs a l lows to t 1296 un ique names to be generated . Th is shou ld be su f f i c ient s ince a name is generated on ly when a IonK name can not be t runcated w i thout conf l i c t .

    A l l var iab les to be processed (p lus s ix le t te r var iab les ) must be dec la red . The long var ib les a re obta ined by ~cann lng tun dec la ra t ions .

    The program can make the d~st~nct lun betwven loca l and ~[obm[ varxmbl~ names . The on ly ~ loba[ names ~n PORTRAN are suhrnut ine , [unc[ lo~, and co~oo b lock nmme~. G loba l name~ are t r , ,a~ed ~n the ~ame way ~s loca l ~ames.

    [ [ the C$MODUI.E opt ion ~ ~sed thor: a l l g loba l names are mapped in to ~ un ique name genermted f rom a fm~r le t te r p re f ix ~hat can be ~pec i [ ied by the u~er w i th CSMODOI.E opt ion card . The las t ~wo cb~racter~ are obta ined n the ~ame way as fo r the loca l name~. The defau l t m "MO~". H the u~r doe~ not want a g loba l name changed, the name mu~ be put ~n ~ C$VIS I8LE opt ion card . Names on the v i s ib le opt ion caCd w i l l not be procem~ed n any way, even ~[ ~bey are longer then s~ characters . The names mus~ be separated by: a cuba , tab , or b lank . A~ many C~VISIBLE card~ u~ ~vc , .~sary may be u~eo.

    S ince the 5o~ware Too l~ macro processor ~s ca~e ~ependent th~ prosram wam wr i t ten to be ca~e dependen~. Var [mbles ~n d i f [e ren~ c~me mre d~[~erent var [ab le~ even when ~pe l led the ~am~. [ t i s the u~r~ respons ib i l i ty to b, con6~tan~ ~ us ing upper and luwer ca6e name~

    Code that ~uppor ts the oge o f unde~corv~ as va l id ~b~acters ~n var iab le names is ~nc luded, bu protected by .~ boo lo~ :ou~tan l because the ~acro processor ~ust be od~[[ed :o t r~a~ underscores a~ va l id a lphanumer ic characte I~. Tb,. Co~8~an[ "}'R_USCORE" c;t]~;[ ~)e s.,[ to t rue ~n ot ter fo r ib i s proKram to proces~ :mdeIsc~, t , . s .

    Imbeded b lank~ ~() a var iab le name are i l l ega l , l on f i:ames ou~t ~ not be sp l~t acrns6 card boundar le~ wi th Con l :nua l l (~n , ,r: i~

    A symbol ~ta ; , . tab le x~ u~ed :o det*.rml~,, ~: . , :.[,~t,,m,.nI :s a i dec larat lon to be ~cann~,(~.

    The program ~ead~ [tom s tandard ~nput and wr~tea t: , ~tandard output}

    INPUT . . . FORT~N aource that has any C$1NChUDES processed OUt.

    I t there are VAX tab convent ions , or end o[ l ine co - -eats

    ~n the ~ource i t shou ld [~r~t be processed by "~H2STD". S ta l ln tng te rminatea wxth eof .

    OUTPUT . . . A [ l~L el de ILne ~tatemen/~ comparab le w l th the So l /ware too I~ macro procesBor .

    USE OF O~ION COUNT CARDS - - example c$f lebug t rue - - d tagaost i cs on ( t rue) , o [ f ( ra i se ) - de /~u l t cSmodu le b t p[oc~s under~core~ } s tandard vor labD, name szzv } cu lumn 6 } un ique name pre f ix length }

    150 Adv. Eng. Software, 1985, Vol. 7, No. 3

  • TYPE namestr chr i s t t . _ l l s~ t _var l~st t _ .namel i s t

    war card : s t r ing ; end_dc l : zn teger ; in_s ix l i s t : 0 . .~XL IST ; namel i s t : t _namelzs t ; in vs l i s t : O..MAXLIST; v ie_ l i s t : t _var l i s t ; v i s l i s t c t : zn teger ; s ix char l i s t : t _var l za t ; l as twasdc l : boolean;

    : packed ar ray[ l . .~AXVARLEN]o f C~ARACTER; - se t of 0. .127; { C~L~RACTER - eodfile } - (GLOBAI . , I .OCAL,VIS IB I .EL IST,S IXI . IST ) ; : a r ray l l . .~AXL lgT] of namest r ; ~ ar ray l l . . ,AXL lgT lo f record

    scope : t _ l i s t ; tx t : namest r ;

    end; { record }

    l ine of fo r t ran code } end o f dcl name } cur rent number in s tx_char_ l i s t } record of l ong names and scopes } cur rent number in namelist } g loba l names not to be changed } cur rent number in v ia_ l i s t } l i s t of s ix char . vat . names } cont inuat ion card f lag }

    sy l lab le modu le_ f lag : boo lean; DEBDG : boo lean;

    { s t r ing constants } s rea l : namestr s in tgr : nsmest r s lgc l : namest r I cmplx : namest r ; sbyte : ns~est r ; sdb le : nsmest r ; schar : namest r ; s fnc tn : namestr; sco~ ~ namestr; subrtn : namestr;

    defstr ; namestr;

    ( option s~rings ) sdebug na~st r ; v is ib le na~e. t r~ mo~mle namest r ; unique namemtr ; g lob_pre f lx n~est r ; l o t _pre f ix n~est r ;

    delimiters alpha a lp~nu~er~c

    : a r ray[LETA. .LETZ, I . .SYHTABSIZE] of i n teger ; { t rue if module option xs invoked } { t rue - -> wr i te out dzagnost i cs }

    resl } znteger ) l og ica l ~ complex } byte } doub leprec is ion ) character } function ) co - -on } subrout ine )

    define - - fo r output }

    { pre f ix fo r g loba l names } { pre f ix fo r loca l na~es }

    chrset ;{ on a s~ l le r ~ch ine these } chr i s t ; { se ts cou ld be s lde smal le r } chrset ; { than the fu l l asc i i se t i f necessary }

    ( ********************** genera l tes t funct ions *********************** }

    {1 . . . . . . . . . . . . . . . . . l ower . . . . . . . . . . . . . . . . . } FUNCTION l~er ( in_ch : CIL~RACTER) : CHARACTER; { re turns a in lower case } { assumes d i f fe rence between upper ~ lower case i s a constant } vat ch : CHARACTER; Beg in { lower )

    i f iu_h in [o rd( 'A ' ) . .o rd (Z ' ) ] then ch : - in ch ord( 'a ) - o rd ( 'A ' ) _

    e l se ch : - in ch ; lower : - ch ;

    End; { l~er}

    (~ - in vat l i s t ) o r f lag ; i f not f lag then beg in

    in vat l i s t : " in vat l i s t * I ; namel i s t | in_vat_ l i s t ] . tx t : - n~ae; namel i s t [ iu . _var_ l i s t ] . scope : - I type ;

    end; { i f not f lag } end; { loca l , g loba l }

    S IXL IST : beg in i f not i n l i s t (n~me,s i~_char_ l i s t , in_s ix l i s t ) then beg in

    i n_s ix l i s t : - i n_s ix l i s t * 1; six char l i s t [ in_s~x l i s t ] : - name;

    end; { i f ) end; ( s ix l i s t }

    V IS IgLE~IST : beg in i f not in l i s t (name,v i s_ l i s t ,v i s_ l i s t _e t ) theu beg in

    v im l i s t c t : - v im l i s t c t + 1; v ia_ l i s t [v ie_ l i s t _e l ] : - name;

    end; { i f } end; { v i s l i s t }

    end; { case } end; ( put_ in_ l i s t }

    (1 . . . . . . . . . . . . . . . . . . . . getvar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . } funct ion getvar (vat s : s t r ing ; vat vars tar t : in teger ;

    vat out : namest r ; vs r lea : in teger ) : in teger gets s var iab le name de l imi ted by wh i te space or a co~a. assumes var iab le name s tar ts w i th In a lpha character . INPUTS s - - ear ing to get var lah le f rom

    vsrs tar t - - s ta r t look ing fo r var iab le

    OUTPUTS out - - var iab le na~e found, te rminated w i th a ENDSTR character .

    l eu - - l ength o f var iab le obta ined vars tar t - - f i r s t char o f the var iab le

    i~T~I$ o~e o f the to l lo~ iu~ in tegers - - the po l i t ion o f the f i r s t de l~ i t ing character

    a f te r the var iab le - - 0 ind icates las t var iab le on l ine was got ten - - -1 ind icates no var iab le was got ten and so l

    vat j , tp , i : in teger ;

    beg in ( &et~ar }

    i : - v l r s ta r t ; wh i le (not ( s i l l i n a lpha) ) and

    (s [ i l ENDSTR) and ( i

  • L : - k + l ; j : - j 1

    ~nd; ( ~h i le }

    out [ j l : - Eb~)ST~; tp : - i ; l en : " j - l ;

    i f no t ( * [ i l ;n de l imi te rs ) then beg in measage( 'GE~tAR: i l l ega l character in var lab le hams ' ) ; puts t r (a ,S~DOUT) ;

    end; { i f oat i n de l imi te r~ }

    { see i f var iab l r i s the l as t one on thv iu : , ' / whi le (not ( s [ i ] in a lpha) ) and

    ( i < ~{AXSTRING) and (s i L l ENDSTR) do t :- t ~;

    I f ( s [x [= ENDSTR) th,,n ~t ( j > 1) then getvar : : 0 { las t w,~rd on ~lt:r } e lse getvar := -'1 { no word ,~n [ lu r ~

    e l se getvar : - rp ; { gains Wt'[~; ~I: [l:c : It;'*

    i t debug then beg in write( 'gETVAR: var" " i ; t := l ; repeat

    wr i te (out [~ l ) ; i : - i + 1;

    unt i l (out{~] " ENUSTR) or l i " ~XV^RI .EN) ;

    ~r t te ln , end; { debug )

    end; { getvar }

    {1 . . . . . . . . . . . . . . . . . f tnd_subst r . . . . . . . . . . . . . . . . . } FUNCTION f iad_subst r (s t r : s t r ing ; subst r : namest r ;

    ~ublen : ~nteger ; ~a~ ~nds~b~tr : l n teger ) :boo lean ;

    Searches for # subst r in the a r t Input . I f a character fa l l s the search ts car r ied out us ing that charact~. r and sh i f t ing the window pos i t ion . When a character Is marcher% the compar i sons cont inue and wrap around the window. D is regards the cane of both the s t r ing ant* the subs[ r ing . Ref . "Ads for r iper |anted Program~.rs"

    vat matched : in teger ; wpos : in teger ; sublnd' t ln teger~ f lag : boo lean ;

    Beg~n ( f ind subst r } matched : - O; wens := O; sub index : " l ; f l ag := la l se i endsubat r := 0; wh i le (matched < sub len) and

    (s t r ]wpos sub ien] ENDSTR) and ( (upos sub len) < HAXSTRIN(;) do

    i f l ower (s t r [wpos+aub inde[) " l ower (subst r [ subzndex[ ) thee beg in m~tched : - matched l ; sub index := sub index mod sub len + 1;

    end vlb~. Dt~ll l

    matched := 0~ wpos : - wpus ; ,

    end ; { i f } I I ta~tched - sublef l then beg in

    f lag :" t rue ; rndsnbst r : - wpos + sub len ;

    ~nd ~ l ind s t lhs t r : - tla~x;

    gild; { t lnd_subst t }

    ********************** t: ,p I rv , , l prors **************************

    {1 . . . . . . . . . . - . . . . gensymtab l , . . . . . . . . . ~ . . . . . . . . . ' PRC)CEI)I:R~ gensymtab~P, ~ gen( ' ra tv tL~' ~ymb~ ~,t.,~, (aD~t'f

    vat ] : i n teger ; pt : ~ntegr r ; { tah l , , p ,} ln t~r t ('h : CHARACTERs

    *2 . . . . . . . . . . i ns t* l . . . . . . . . . . . ~ PROCEIXJRE Ins ta l ( symbo l : names[ i ) ;

    { Inn[a l l l y r i ca l tn the symbol s ta te tab le ) vat t r i te , l a t t t ta te , l : i n teger ; *wara iug : w i l l not work ta r tram[, be ing subset of another name I

    ~eg in { iu ta l } ~ : " 1; l as ts [a te := 1; s ta te : " ~ymLab le [symbo l [ l} , las ts ta te~i

    whi le s ta te >* 0 do beg~n I :" x ~ 1; la l t s ta te : - s ta te ; s i l t s :~ symtab le [symbo l [ l ] , l as ts ta te ] ;

    end ;

    symtab le [symbo l [ l [ . l l s t s ta t~ ' l :~ p t l , wh i le symbo l [ i ] ENDSTR do beg in

    gym[ab le [symbo l [ i] ,pt : - p t l ; pt :~ pt I ~ ~ := te l ;

    end; symtab ie [symbo l [ i - l~ .p t - I ~ '),

    End; { ins ta l }

    Begin { geoaymtab l r } pt := I ;

    152 Adv. Eng. Software, 1985, Vol. 7, No. 3

    { ln i t ta l~ze the symbol tab le to minus I ) fo r j : - I to SY~ABSIZE do

    for ch : " o rd ( 'a ' ) to o rd ( ' z ' ) do symtah le [cb , j ] : - - l ; { in i t ia l t ze }

    { put k~y ~ords into tho table } i n~ta l ( s rea l ) ; i~ta l ( s~n~r)~ i na ta l ( scmplx )~ in~ta l ( s lgc l ) ; ~nsta l ( sbyte ) ; in~ta l ( sdb le ) ; in~ta l ( schar ) ; ~o~ta l (~foctn) ; i ns&a l (scomm); ~nsta l ( snb~tn) ;

    ~nd; * o f ~ensysmbol tab le )

    ( l . . . . . . . . . . . . get names . . . . . . . . " . . . . . . . . . . . } PROCEDURE i s*names(card : s t r ing ; / , tr l l l~t,gcr J ~ { get~ thv na~e~ o~ the ~cl l~e a~c put~ the~ ~u ~h,. { appropseate ] lE t , { INPUTS card -- s t r~ng ,~t (~,rtran ~ourcv codv ( p t r pos i t ion at enc at dc l keyword

    vat count , I : i n teger ; saved : boo lean ; name : namest r ; gpt r : in teger ; ( pos i t ion po in ter ) p tbeg in : in teger ; ( beg in~ng po in t of a vat . name ptend : in teger ; ( end of varxb le name }

    (2 . . . . - - . . . . . . . . . L ive_name . . . . . . - . . . . . . . ~ . . . . . . ) PROCEDORE Dave_name(name : names*r ; len : zn teger ; I Lype : ~_ l i s t ) ; ( saves a name in the appropr ia te l i s t ~f i t zs not a l ready there } ( Uses a sequent ia l search th ru the l i s t tu ~znd the ~ame. } ( ~NPUT$ na~e -~ name tO be aa~ed. } { Inn -- length of name to be saved. } { itype -- Izat type. }

    vat u f lag : boo lean ;

    Begin { Dave" nlme }

    nf lag :: (hms.underscore(name) and PR ~SCORE): if (Inn > stdsgze) or *uf lag) then put. in. l lst(uame,ltyp~.) else if ( I type " g lobal ) and module f lag and

    ( not in lzst (name,v is_ l i s t ,vzs . . l i s t _~ 0 ~h~n

    s lve . _~ame(name,count ,g loha l ) ; end ( i f the~ }

    e l se z! f ind subst r (card ,subr tn ,10 ,gpt r~ th, 'n ~,,.gln las twasdc l : - fa l se ; p t r := gpt r 1; i f getvar (card ,p t r ,name,eount ) - 0 thee

    save name(t.ame,count,g!obal)~ end { e l se If

    e l se begin coutlt : - C. pit. rid : , pet * pos~t to t : a l te r ,h t .~k .d~ t

    vh i le p t r > O do beg in ptbegl t~ := ptend; p t r : - g~tvar (card ,p tbeg ln ,name,count )~

    xf p t r > 0 then ptend :o p t r

    c i te F reud : - p tbeggn * count ;

    l i ved :~ false; i epe i~

    i f c l rd [pteDd] - SLASN then beg in ( co~=ou b lock ~sme )

    aave_oame(name0countog loba l ) ; saved : - t rue ;

    end e l se zf card[ptend] - LPAREN ~hen begzn { an ar ray ie beng dec la red , on ly need the namr }

    save_name(name,count . loca l ) ; saved := t rue ; j : - pten~; repe~

    j : '~ . I ; unti l (card[ j ] = ENDSTR) or

    (card[ j ) - RPAREN) ~ (j >- ~XSTRING ~)~

    gg card[ j ] - RPAREN the~ ptend : - ) e lse if card( j] - ENDSTR [hen ptend :~ j "" I~

    end;

    p~eud :- p~end ~; unti l (cmrd lptend} " Eh~STR) or

    (car~Ip&e~d] in alpha) or (tend >- ~ ING) ;

    ~ not eared then aave_~ame(n~me,couu~,~oca l} ;

  • end; { while } end; { if find_substr... }

    End; { getnamee }

    {I ....... - . . . . . . . . . . . . output_defines . . . . . . . . . . . . . . . . . . } PROCEDURE output_defines;

    generates a table of defines to be used with the macro processor the defines are written t~ standard output global names not in the visible list are mapped into sequential unique names using "gloh_.prefix". local nares are truncated. If truncation causes a conflict then a new name is generated using "loc~prefix". code is supplied for handleing underscores, but must be activated at compile time with the constant "PR_USCORE"

    CONST MAXSUFCHAR - 36; { 0..9,A..Z }

    TYPE sufix~cntr = record s|,s2 : integer; { counters for the last 2 chrs.

    end; { record }

    vat i , j : i n teger ; tname : uamestr; gvar , lvar : su f ix_cnt r ; ch_c t r : CHARACTER; ( character counter } su f ix : array[I . .HAXSUFC~AR] of CMARACTER; { used to get the las t two characters of the unique name }

    {2 " = ' = " . . . . . " -= ' ' ' ' ' " t runcate - - - - - - - - - - - - - - - - - - - - - - - - - - } ~rocedure t runcate( inname : namest r ; var outname : namest r ) ;

    T runcates a name to the STDSIZE and tacks a ENDSTR on the end. I f a name has underscores and they are to be processed they are removed and the result is truncated if it is still > STDSIZE BUG: does not check for conflict with names shorter than six

    characters . Conf l i c t cou ld occur i f removing the underscores generates a name shor ter than s ix characters that a l ready ex is t in the fortran source code .

    INPUTS inname - - name to be t runcated , can have underscores OUTPUTS outname - - t runcated name end ing w i th a ENDSTR

    vat j,k : i n teger ; beg in

    if PR_USCORE then begin i f has_underscore( inname) then beg in

    k :" 0; j := 0; repeat

    j : - j l ; if inname[j] UNDERLINE then begin

    k :- k + 1; inname[k] := inname[ j ] ; { j >- k so use same var iab le }

    end; { xf inname } unt i l ( j = MAXVARLEN) or (inuame[k] - ENDSTR);

    end, { if has_underscore } end; ( i f PR_USCOEE )

    j : '0 ; repeat

    j : - j l ; outnnme[ j ] : - i nname[ j ] ;

    until (j - STDSIZE) or (outname[j] - ENDSTR); if outname[j] ENDSTR then

    outname[STDSlZE + I] := ENDSTR; end; { truncate }

    {2 .. . . . . . . . . . . . . . . . . . write_new_name . . . . ~ . . . . . . . . . . . . . . } PROCEDURE write new name(prefix : namest r ; vat su fc t r : sufix_cntr);

    generates a unique name for a variable name using the user supplied prefix, or the default prefix. INPUTS prefix -- first part of new name

    sufctr -- counters for the last two characters of the new name.

    OUTPUTS sufctr -- incremented by i

    vat j : i n teger ; geg in ( ~rlte new ~me }

    fo r j := l to PREFIXLEN do put t (p re f ix [ j ] ) ; putc (eu f i z [eu fc t r . s l ] ) ;

    putc (~ iz [su fc t r .e2] ) ; ufctr.~2 : " sufctr.s2 + l; i f s~fc t r ,e2 = ~AXSUFC~L~R+I then beg in

    su fc t r . s2 :- O; su fc t r . s l :- su fc t r . s l + 1; if su fc t r . s l > MAXSUFCHAR then

    mes~age( 'Too many un ique var iab les requ i red ' ) ; end; { i f eu fc t r . . . }

    End; { write new name }

    geg in { output_def ines } gvsr . s l := 1; gvar . s2 :~ 1; l va r .e l := l ; I var . s2 : " 1;

    ( i n i t ia l i ze sufix ar ray } i : - 0; fo r ch~ctr : - ord('0") to ord('9") do begin

    i : - i + I; su f ix [ i ] : " ch_c t r ;

    end; ( for ) fo r ch._ctr := ord( 'A ' ) to ord( 'Z ' ) do beg in

    i :- i + 1; sufix[iJ : - ch_c t r ;

    end; { for )

    for i : - I to in war l i s t do beg in

    j : " I ; repeat

    putc (de fs t r [ j ] ) ; j : - j +1;

    until (de fs t r{ j / " ENDSTR) or ( j " b~XVARLEN); puCc(LPAREN);

    j : - 1; repeat

    putc(namelist[i].txt[j]); j := j l ;

    until ( j >- MAXVARLEN) or (namelist[il,txt[j] - ENDSTR ); putt(COMMA);

    if (namelist[i].scope - GLOBAL) and (module_flag) then begin { names in the visible list were never saved in namelist }

    write new name(glob_pref ix,gvar); end { if global }

    else begin truncate(namelist[i].txt,tname); if inlist(tname,six char list,in_sixlist) then

    write new name( loc~ref ix,lvar) else begin { put t runcated name in the six char list }

    in_sixlist :- in._sixlist * I; s ix char list[in sixlist] := tname; ( write out truncated name ) j : -1 ; wh i le ( tname[ j ] ENDSTR) and ( j < HAXSTRING) do beg in

    putc ( tname[ j ] ) ; j :- j + I;

    end; ( while }

    end; { e lse } end; { e l se }

    putc(RPAREN); putc(NEWLINE);

    end; { for i :- I to in vat list } End; { output_defines }

    {I ~ . . . . . . . . . . . . . . pr_opt ion " . . . . . . . . . . . . . . . . . . } PROCEDURE pr_option(card : string); war opt~os , lp , len : integer;

    sour : aamestr;

    Beg in { pr_opt ion ) opt_poe : " 3 ; l p := getvar (card ,opt__pos ,sout , fen) ;

    if sequa l (sdebug,sout ) then beg in i f getvar (card , lp ,eout , len) >=0 then beg in

    i f sour[l] i n [o rd ( ' t ' ) ,o rd ( 'T ' ) ] the~ DEBUG :" t rue

    e l se DEBUG := false; end; ( if getvar... }

    end ( if sequal }

    e lee if sequa l (modu le ,sout ) then beg in modu le_ f lag := t rue ; i f getvar (card , lp ,eout , len) >- 0 then g lob~pre f ix : - sour ; i f DEBUG then wr i te ln ( 'PR_OFT lON: module card found ' ) ;

    end

    e l se if sequa l (uu ique ,sout ) then beg in if getvar (card , lp , sout , len) >ffi 0 then I oc~re f ix := sour; if DEBUG then writeln('PR_OPTlON: unique card found');

    end

    else if sequal(visible,sout)then beg in repeat

    Ip :- getvar(card,lp,sout,len); if (Ip >= O) then

    put_in_list(sout,VISIBLELlgT); until (Ip

  • s lgc I [5 ] := ord( ' c ' ) ; s lgc l [6 ] := ord( 'a ' ) ; s lgc l [7 ] := ord( ' l ' ) ; slgcl[8] := ENDSTR;

    sbyte[ll := ord(~b'); sbyte[2] := ord('y'); sbyte[3] := ord(~t~); sbyte[4] := ord( 'e ' ) ; sbyteI] := ENDSTR;

    sdble[II := ord('d') sdble[2] :- ord('o ~ ) sdhle[3] :~ ord(~u ") sdble[4] :- ord('b') sdble[5] :- ord('l') sdble[6] :~ ord('e') sdble[7] := ord('p'); sdhleIS~ := ord(~r'); sdbleIg] := ord(~e'); sdble[10] :ffi ord('c'); sdble[ll] := ord('i'); sdble[12] := ord('s'); sable[13] := ord('i*); sdble[14l := ord('o'); sdble[15] :ffi ord('n'); sdble[16] := ENDSTR;

    schar[ll := ord(*c~); schar[2] := ord('b~); schar[3] := ord('a'); schar[4] :ffi ord('r*); schar[5] := ord('a*); schar[6] := ord('c'); schar[7] := ord('t'); schar[8] := ord(*e'); schar[9] := ord('r'); schar[10] := ENDSTR;

    subrtn[l] :- ord(*s'); subrtn[2] := ord('u'); subrtn[3] := ord('b'); subrtn[41 := ord('r'); subrtn[5} := ord('o'); subrtn[6] := ord('u'); subrtn[7] := ord(~t'); subrtn[8] := ord('i'); subrtn[91 := ord('n*); subrtn[lO[ := ord('e~); subrtn[ll[ := ENDSTR;

    scomm[l] := ord('c'); sen=f2] := ord('o'); sco f f31 := ord('m'); scomm[4] := ord('m'); scomm[5] := ord('o'); scomm[6] := ord( 'n ' ) ; scowl7] := ENDSTR;

    s fnc tn [ l} := ord( ' f ' ) ; s fnc tn [2] := ord( 'u ' ) ; s fnc tn [3] : - o rd ( 'n ' ) ; s fnc tn [4] := ord( ' c ' ) ; s fnc tn [5] := ord( ' t ' ) ; s fnc tn{6] := ord( ' i ' ) ; s fnc tn [7] : - o rd (*o ' ) ; sfnctn[8] :ffi o rd ( 'n) ; sfnctn[9] := ENDSTR;

    visible[l] := ord('v ~ ) visible[2] :ffi ord('i') visible[3] :ffi ord('s') visible[4] : - ord('i') visible[5] :- ord('b') visible[6] :- ord('l ~) visible[7] :ffi ord('e') visible[8] := ENDSTR;

    module[if := ord('m*); module[2] := ord(*o'); module[3] :ffi o rd ( 'd ' ) ; module[4] := ord('u'); module[5] := ord('l'); module[6] :~ ord('e'); module[7] := ENDSTR;

    unique[If :- ord('u'); unique[2] :~ ord('n'); unique[3] := ord('i'); unique[4] := ord('q'); unique[5] :- ord('u'); unique[6] := ord('e'); unique[7] := ENDSTR;

    sdebug[l] :ffi ord('d'); sdehug[2~ := ord('e~); sdebug[3] :- ord('b'); sdebug[4] := ord('u'); sdebug[5] := ord('g'); sdebug[6] := ENDSTR;

    defstr[l] :- ord('d'); defstr[2] := ord('e'); defstr[3] := ord('f'); defstr[4] := ord('i); defstr[5] :~ ord('n); defstr[6] := ord('e); defstr[7] := ENDSTR;

    { default value of g lob~ref ix for global names } g loh~ref ix[ l ] := ord('M'); g lob~ref ix [2] := ord('O');

    154 Adv. khg. Software, 1985, Vol. 7, No. 3

    glob~ref ix [3] := ord('D'); g lob~ref ix [4] := ord('U');

    loc~ref ix[ l ] := ord('U'); loc ~refix[2] := ord('N'); loc~ref ix [3[ := ord('l'); loc~ref ix[4] := ord('O');

    gensymtable; ( initialize symbol state table }

    debug := false; lastwasdl :- false; { inltialize for continuation checking } module_flag :~ false; in vat list :* O; ( initialize llst counters } in_sixlist :* O; vis__list_Ct := O;

    End; { initialize )

    {I ............. check dcl . . . . . . . . . . . . . . . . . } _ FUNCTION check_dcl(card : string; var end_dcl : integer) : boolean;

    checks to see if a card is a declaration card. Uses the symbol } state table to determine if the card has a reserved word on it )

    input -- card, a line of fortran code } output -- end_dcl, positlon of first character after the }

    end of the reserved word. } returns -- true if dcl card is found. }

    var cptr : integer; { card pointer } state : integer; { used in symbol state table } dc l f lag : boolean; ch : CHARACTER;

    Begin { check dcl } _ dc l _ f lag false; cptr := I; state := I;

    while (state > O) and not(card[cptr] = ENDSTR) do begin cptr :- cptr + 1 ; ch := lower(card[cptr]);

    if (ch in alpha) then state := symtable[ch,state]

    else if not(ch in [BLANK,TAB]) then state := -1; { not a dcl }

    if state = 0 then dcl_flag :- true; end; { while }

    if dcl_flag then end dcl := cptr + 1 else end_dcl := 0; if debug then writeln( 'check dcl: ",dc[_flag); check_dcl := dcl_f]ag;

    End; { check_dcl }

    {I . . . . . . . . . . . . . continued . . . . . . . . . . . . . . . . . ) FUNCTION continued(card : string): boolean; { the first six columns are searched for a non blank character ( i f that character i s a tab then the l ine is nnt co t l t lnued { i f the f~rs t non b lank character i s in column s i s and not a { tab or 0 then the l tne ts cont inued

    vat cp : 0..MAXSTRING; { card position } cflag : boolean; { continued flag }

    Begin { continued } ep := l; cflag := false;

    while (cp COL6) or (card[cp] = TAB) then cflag := false else if cp ~ COL6 then begin

    if card[cp] " ord('0") then cflag :- false else cflag :" true;

    end; ( else if } continued := cflag;

    End; { continued }

    { ******************** main procedure *************************

    Begi~ {main}

    initio; { initializes software tools constants,types and variables

    initialize; { initializes all the variables, arrays and tables used in the main procedure }

    while getl ine(card,STDIN,MAXSTR) do begin if (lower(card[l]) = LETC) and (card[2] = DOLLAR) then

    pr_option(card) else if not (lower(card[If) in [LETC,STAR]) then if check_dcl(card,end_dcl) then begin

    getnames(card,end_dcl); lastwasdcl := true;

    end else if (lastwasdcl) and continued(card) then

    { if a line is continued the text has to start } { in at least column 7 } getnames(card,7)

    else lastwasdcl := false; end; { while }

    output~define s; End. ( longname }

    DEFINE.SFT Processes the define statements

    { DEFINE PROGRAM (sft) ( ~ FUNCTION -- define reads from standard input, looking for macro

  • definitions of the form define([dent,string). } and writes tO standard output with each subsequent instance of the } the identifier ideal replaced by the sequence of characters string.} String must be he,lanced in parentheses. The text of each defini- tion proper results in no output of text. Each replacement string is rescanned for further possible replacements, permitting multi- level definitions.

    NOTE this program may be modified to handle underscores by adding an underscore to the valid characters of the util ity "isalphanm~"

    EXAMPLE define(endfile,(-l)) define(done,endfile)

    if (getit(line) = done) then putit(sumline);

    if (getit(line) " ( - i ) ) then put it ( s~l ine) ;

    BUGS A recursive definition such as define(x,x) will cause an infinite loop when x is invoked

    REFERENCE Kernighan &P lauger , "Software Tools in Pascal" 198l ~d ison-Wes ley Publishing Company, Reading, MA

    wrapper (CU) -- this is the wrapper for all the software tools This next line inherits all the global definitions that go along

    with the software too ls . [ inherit ('userl : [bllb.sof ttool .environ} globdefs ,env') ] program wrapper( input ,output ) ;

    { define -- simple string replacement macro processor } procedure define;

    { defcons -- coust declarations for define } coast

    BUFSIZE = 500; { size of pushback buffer } MAXCMARS - 5000; { size of uame-defn table } MAXDEF - MAXSTR; { max chars in a defn } MAXTOK = MAXSTR; { max chars in a token } HASRSIZE - 53; { size of hash table }

    { deftype - - type definitions for define } type

    charpos = 1..MAXCHARS; charbuf - a r ray [I..MAXCHARS] of character ; s t type - (DEFTI~E, MACTYPE); { symbol tab le types ) ndptr = Andblock; ( po in ter to a name-defn block ) ndblock =

    record { name-defn block } name : charpos; defn : charpoa; kind : sttype; nextpt r : ndptr

    end;

    {defvar - - vat dec la rat ions for def ine ) vat

    hashish : a r ray [I..HASHSIZE] of ndptr ; ndtab le : charbuf ; next tab : charpos ; { first f ree pos i t ion in ndtab le } bur : a r ray [ I . .BUFSIZE] of character ; { for pushback } bp : 0..BUFSIZE; { next ava i lab le character ; init=0 } defn : s t r ing ; token : s t r ing ; toktype : s t type ; { type returned by lookup } defuame : string; { value is "define" } null : string; { value is "" }

    { defproc - - procedures needed by define }

    {cscopy - - copy cb[ i ] . . , to s t r ing s } procedure cscopy (vat cb : charbuf ; i : charpos;

    vat s : string); vat

    j : integer; begin

    j : - 1; whi le (cb[ i ] E~DSTR) do begin

    s[j] :- cb[ i ] ; i :- i+ l ; j :" j + I

    end; s[j] :- ES~STR

    end;

    { sccopy -~ copy string s to cb[i] . . . } procedure sccopy (vat s : s t r ing ; vat cb : charbuf ;

    i : charpos) ; vat

    j : integer; begin

    j : - I ; while (s[j[ ENDSTR) do begin

    cbIi] := s[jl; j := j + I; i := i+ 1

    end ; cb[ i ] : " ENDSTR

    end;

    ( putback - - push character back onto input }

    procedure p~tback (c : character ) ; begin

    if (bp >- Bt~SIZE) then er ror ( ' too many characters pushed back ' ) ;

    bp : - bp + I ; buf [bp] : - c

    end;

    ( getpbc - - get a (poss ib ly pushed back) character ) funct ion getpbc (vat c : character ) : character ; beg in

    i f (bp > O) then c := buf [bp]

    e l se beg in bp : - i ; buf[bp} := getc (c )

    end; if (C ENDFILE) then

    bp := bp - i; getpbc := c

    end;

    ( pbstr - - push s t r ing back onto input } procedure pbstr (war s : s t r ing) ; vat

    i : integer; begin

    for i :- length(s) downto I do putback(s [ i ] )

    end;

    { gettok -- get token for define ) function gettok (vat token : string; toksize : integer)

    : character ; vat

    i : integer; done : boolean;

    begin i := I ; done : - false; while (not done) and (i ~ toksize) do

    if ( isalphanum(getpbc(token[i]))) then i := i+ l

    else done : - t rue ;

    if (i >- toksize) then error('define: token too long');

    if (i > 1) then begin { some alpha was seen } putback( token[ i ] ) ; i : " i - 1

    end; { e lse single non-alphanumeric ) token[i+l] := ENDSTR; gettok :- token[l}

    end;

    ( getdef - - get name and def in i t ion } procedure getdef (vat token : s t r ing ; toks i ze : in teger ;

    vet defu : s t r ing ; de fe ize : in teger ) ; vat

    i , n lpar : i n teger ; c : character ;

    begin toRn[ l} : - ENDSTR; { in case of bad input ) de fn [1] : " ENDSTR; i f (getpbc(c ) LPAREN) then

    message( 'de f lne : missing l e f t paten ' ) e l se if (not i s le t te r (get tok( token , toks i ze ) ) ) then

    message( 'de f ine : non-alphanumeric name*) e lse if (8etpbc(c ) COI~fA) then

    message( 'de f ine : miss ing cou~a in def ine ' ) e l se begin { got " (name," so fa r }

    while (getpbc(c ) - BLANK) do ; ( sk ip lead ing blanks )

    putback(c) ; { went one tOO far } n lpar :m O; i := I ; whi le (n lpar >= O) do beg in

    i f ( i >" de fs l ze ) then er ror ( 'de f lne : de f in i t ion too long ' )

    e l se i f (Setpbc(defn[ i ] ) = ENDFILE) then er ror ( 'de f iue : miss ing r ight paren ' )

    e l se i f (de fn[ i ] = LPA~EN) then n lpar : " n lpar + I

    else if (de fn[ i ] " RPAR~N) then n lpar : " n lpar - 1;

    { e lse normal character in defu[i] } i : ' i+ l

    end; defn[ i - l ] : - ENDSTR

    end end;

    { in i thesh - - in i t ia l i ze hash tab le to n i l } procedure in i thash ; vat

    i : I..HASHSIZE; begin

    nexttab := l; { first free slot in table } for i : " I to HASHSXZE do

    hashtab[i] :~ nil end;

    ( hash - - compute hash funct ion of a name ) funct ion hash (vat name : s t r ing) : in teger ; vat

    i, h : i n teger ; begin

    h : - 0; for i : - I to lem~tb(name) do

    h : " (3 * h + name[ i} ) ~od ~ASHSIZE; barb : - h + 1

    end;

    { hashf ind - - f l ad ~me i~ hash tab le } funct ion hashf ind (vat name : s t r ing) : ndpt r ; vat

    ad , Vo Z: oo

  • p : ndptr; tempname : strlng; found : boolean;

    begin found := ~alse; p :- hashtab[hash(name)]; while (not found) and (p nil) do begin

    cscopy(ndtable, p'.name, tempname); if (equal(name, tempname)) then

    found :~ true else

    p :~ p'.nextptr end; hashfind :- p

    end;

    { install -- add name, definition and type to table } procedure install (vat name, defn : string; t : sttype) vat

    h, dlen, nlen : integer; p : ndptr;

    begin ulen :- length(name) + i; { I for ENDSTR dlen :- length(defn) + I; if (nexttab + mien + dlen > HAX~ARS) then begin

    put~tr(n&me, SYDERR); error(': too many definition~')

    end else begin { put it at front of chain }

    h :- hash(name); new(p); p^.nextptr :~ hashtab[h]; hashtab[h] :- p; p~.name :- nexttab; secopy(n&m~, ndtable, nexttab); nexttab :- nexttab + mien; p^.defn :" nexttab; seopy{de[n, ndtable, nexttab); nextt~b :~ nexttab + dlen; p*.kind :l t

    end end;

    { lookup -- locate n~me, get defn ~nd ~ype from t&ble } function lookup (v~r u~me, defm : s~rimg; vlr t : sttype)

    boolean; va~

    p : udptr ; ~,eK~n

    p :- ha~hfznd(name): i~ (p - n i l ) then

    lookup :~ fa l se e lse begin

    lookup := t,ue~ cscopy(ndtab lv , p ' .de fn , defn) ; t - p ' . k ind

    end end;

    ( in i tde f - - in i t ia l i ze var iab les for def ine ) procedure in i tde f ; begin

    ( se ts t r ing(defname, "de f iner ) ; } defname[l] := ord( 'd" ) ; defname[2] := ord("e" ) ; defname[3] := ord( ' f ' ) ; defname[4] := ord(" i~) ; defname[5] := ord( 'n ' ) ; dename[6] := ord( 'e ' ) ; defname[7] : - ENDSTR;

    bp : - 0; ( pushback buf fer po in ter } in i thash

    end; begin

    null[l] :- E~DSTR; initdef; install(defname, null, DEFTYPE); while (gettok(token, MAXTOK) ENDFILE) do

    if (not isletter(token[l])) then puts t r ( token , STIIOUT)

    e l se i f (not lookup(token, defn, toktype) ) then puts t r ( token , STI~UT) ( undef ined )

    e l se i f ( toktype u DEF~YPE) then begin { defn getdef(token, HAXTOK, defn, MAXDEF); install(token, defn, HACTYPE)

    end else

    pbstr(defn) ( push replacement onto end; begin { wrapper }

    initio; { Call program here. For example: filter } define

    end. { wrapper )

    xnpu~ )

    l~,q~, ~H~I~ ~. )~.~ .,:~1~, Iz~ 7 ,~.~

Recommended

View more >