Previous: 2 Enhancing the File menu and incorporating your existing code
Next: 4 Graphics in the client area
In this section:
If I am allowed to speculate, it is that you probably had a Fortran application of your own developed some time ago. It may even still be in the form of a listing, in which case you have to type it in line by line and make sure that you have made no mistakes. If you already have a program that works (and you have tested it with FTN95) then skip this whole Chapter. If you are writing a program from scratch, then this Chapter is optional, but I think that it is worth forgetting about Windows interfaces for a while, and just make sure that you have coded the basic algorithm you wish to use starting by reading in the data from a file.
Programs that exist as listings are sometimes found in books, in student theses, or in reports to government bodies (usually) but to all manner of other clients. The very earliest programs will have been written in dialects of Fortran that are very limited by today’s standards, but in practical terms the earliest that you are likely to come across or even to have written yourself would have been written in Fortran 66 (sometimes known as Fortran IV). The ANSI Fortran committee produced an updated version of the standard in 1977, and this is called for obvious reasons Fortran 77. That committee was hard at work in the 80s with the hope that they would publish their standard in 1988, or at least in the 80s so that at least one book refers to it as Fortran 8X – probably hoping for 88. However, they did not finish their work before 1990 so that we have a standard for Fortran 90. Some corrections and enhancements followed in 1995 (from which FTN95 gets its name) and some in the new millennium.
The company Silverfrost took over what had been the Salford University FTN compiler, which had been through Fortran 77 and Fortran 90 versions, and as I write FTN95 contains some, but not all, of the enhancements from Fortran 2003 and 2008, with more being added all the time. What I am confident about, however, is that you will find that the old program looks horrible, lacks comments, and is pretty difficult to follow. You will almost certainly have your work cut out to tidy it up. One of the first tasks that you will have to undertake is to understand what sort of computer your Fortran program was written for, and also which version of Fortran was employed. In the Fortran 66 era, compilers were usually targeted at a specific brand of computer or small range of computers and therefore they implicitly assumed to something about the architecture. It was common to find that the compiler did not implement the full range of statement types and had some of its own tricks up its sleeve in the form of compiler extensions.
Fortran 77 came along at a period of great change. You can imagine that the compiler writers do not get their new version compiler out and fully debugged in the same year as the standard emerges but take some time. There is the additional complicating factor that about the time that Fortran 77 compilers were coming out there was also the launch of the first modern practical personal computer. It was the case that there was a lot in Fortran 77 that some compiler writers chose to leave out, and that their products will what we would call ‘subset’ compilers. Indeed, Microsoft’s first efforts were subset compilers.
Just before the personal computer was launched there was a trend to make what were called minicomputers. Generally speaking, minicomputers had a lot more memory than the mainframes of only a few years before and although the first few generations of personal computer took a while to catch up, it wasn’t long before the memory available on a personal
computer far exceeded what had been provided on a minicomputer or mainframe only a few years before. At the present day, most personal computers will be supplied with what was originally thought to be unachievable amounts of memory. For example, if we measure the memory size of a computer in bytes, the mainframe that I used in between 1973 and 1984 for most of my work had a capacity of about 96k or 96000 bytes. A minicomputer that I used subsequently had about 512k bytes. Even my first PC had half that, and actually more when I bought additional RAM for it. Remember that some of that memory was taken up by the operating system and was not available for user programs, and that the memory has to store the program and all the variables. In those days various things were done to make up for the smallness of the memory and one of those when they were needed, which was a technique called overlaying, and another was to save a lot of data generated part way through a program on magnetic tape or later (when they became available) on a magnetic disk.
In contrast, the machine I am writing this on has a memory of some 32 GB, or 32 000 megabytes, or 32 million kilobytes. If I use one of the compiler options in FTN95, I can write programs that use all of what is left over after the operating system has taken its chunk. To do that I have to compile my programs in what is called 64-bit mode. If I compile them with the alternative (and rather simpler) 32-bit mode I can carve out 2 GB to store the program and its data or with a little bit more effort 3 GB. Even 2 GB is 4000 times more than the minicomputer! The upshot of all of this is that when converting an old program there probably won’t be any chance of running out of memory. Your program will be able to have all the Windows interfacing that you want and even it will be possible to scale up all the arrays so that you can solve much bigger problems than ever you fantasised when you first wrote the program (or whoever wrote it could possibly have imagined). Eventually, I have no doubt that 32-bit programs will be dropped, and only those compiled with the 64-bit option in FTN95 will be allowed, but that point has not been reached yet.
Your next step is to make sure that your program works properly without a Windows interface, because if it doesn’t, then you will struggle to debug the program code at the same time as you are writing the interface.
There are numerous issues to do with compiling an old Fortran program with FTN95, and one of those is getting the hang of the FTN95 system. Another one is that there have been some changes in Fortran, although FTN95 is forgiving in that respect and will compile most things bar a couple, which I will get on to in due course. Then finally computers have changed. The simple fact that you are contemplating turning your program into a Windows program means that you intended to run on a personal computer and that may well be a little bit different to the mainframe that you probably used to develop the program on in that dim and distant past. If you are new to Fortran, then you will probably want to use all the latest fancy facilities in the language and since this is not a Fortran tuition book, you will need your own Fortran textbook. You might be able to work from the appropriate standard, but I’ve never found the Fortran standards to be particularly readable. What’s more the latest Fortran programming tuition books are all rather expensive. I’m sure that’s because they anticipate only tiny print runs. My suggestion for those resurrecting an old program and possibly not anticipating rewriting everything to accord to modern standards is to get an older book, possibly a secondhand or ex-library book, and there isn’t much point in going too far in the modern direction, so a book on Fortran 77 will probably give you everything that you want so for example you might do a lot worse than to look on AbeBooks for Etter’s book: Structured Fortran 77 for Engineers and Scientists, by D. M. Etter, published in paperback in 1990 and available secondhand really rather cheaply. Delores Etter (wonderful name, isn’t it?) also developed books on Fortran 90, also available secondhand.
It used to be the habit of compilers to include a complete manual on Fortran and it may be that you could get hold of an obsolete compiler from somebody like Microsoft and use their description of Fortran instead. If you do that then you have to remember that the instructions are of course tailored to that old compiler.
There is also a very important part of the job of rehabilitating an old program, and that is to remind yourself of what it does and perhaps even just a pretty it up in some way. You have to be a bit cautious doing that just in case you alter something that irrevocably ruins the code!
I said that FTN95 was rather forgiving of old Fortran, and indeed it is, much more forgiving in fact than the people on the Fortran Standards Committee who have declared a number of things persona non grata, by describing them as obsolete, deprecated, or even deleted. Some of those things are facilities that you may well have used and indeed, relied upon. One of the great things about Fortran is that old stuff generally does run, and I think that the Fortran Standards Committee’s members basically hate Fortran and want it to be something else. I have a certain amount of sympathy with this view because I started that part of my life as a (part-time) programmer with a language called Algol 60. I disliked Fortran for a long time because it wasn’t Algol. When Algol just about completely disappeared, I was grateful that I’d had to switch to Fortran!
There are two places in the online help file where the messing around with Fortran is covered, both under the main heading “What’s new in Fortran 95” with subheadings “Deleted features” and “New obsolescent features”. With the exception of “branching to ENDIF”, all of the “deleted features” are still present in FTN95, and branching to ENDIF seems to be an odd one anyway. As far as the “New obsolescent features” is concerned, I think that “fixed form source” is to all intents and purposes a subset of free format, except perhaps in its use of continuation markers and some of the other features headed for the chop will presumably still function.
It is worth checking with the list, especially if you used one or more of the things scheduled at some point for execution, and replace them in plenty of time.
I can’t give a positive recommendation for the use of ‘code polishing software’, although your experience may differ to mine, but generally I find that the result is no improvement or at worst, makes the original source code unreadable.
One of the first issues that you will come across with a very old program is that everything is in capital letters. A change introduced a very long time ago allows you to program in lowercase letters, or to mix them, if you like, with something sometimes called ‘camel-case’. The name ClearWin+ is ‘camel case’ because it has humps. However, Fortran is case-insensitive, and a variable in the program could therefore be written in various ways, such as:
DELTA Delta delta
and not only that, but some other characters are possible including numerals and the rather useful underscore character. Later versions of Fortran allowed longer names, with 6 characters being the norm in Fortran 66, although only 5 were allowed in a subset compiler I used. If the longer names were permitted, then names like this became permissible:
and so on.
The point is that in Fortran the case does not matter, and so the different ways of writing variable names count as all the same.
I tend to still program using capitals, not just from force of long habit but because I can clearly show the difference between program code and comments by using lowercase for the latter. I have tried it the other way round and frankly it doesn’t work so well. I also use lowercase for any debugging code that I slip in and intend only to work temporarily. This is something that I recognise that the compiler doesn’t, but I find it still really rather useful. Occasionally, I use a bit of ‘camel case’ if I want to highlight a variable name. The whole point of this is to explain why I do it in a particular way, but you have to do it your way.
It’s also likely that your program was originally written, if not for punched cards as an input medium, then in something that was laid out in the same way as a punched card. In the historical development of punched cards, they were different sizes and contained different numbers of characters and symbols. By the time they came to be used for Fortran programming, they used 80 columns or had the capacity to have up to 80 characters, and typically had rows of holes that represented characters in a six-bit code. A six-bit code is adequate to differentiate between the letters in a Roman alphabet, numerical digits, a small amount of punctuation and some control codes. The six-bit coding is of course why Fortran in the early days was always programmed in capitals.
Incidentally, because many card punches not only punched a hole pattern but also printed the relevant character on the top of the card it is sometimes possible even if you can no longer read the punched cards directly into a computer, you may be able to read the Fortran statements from the top of the cards.
Some (typically British) computers used punched tape instead of punched cards. The tape had a continuous line of holes for a sprocket and rows of eight holes although they still only operated a seven-bit code because the eighth hole position was used for a parity check. If the punch had not made the appropriate hole in one of the positions, it would be obvious because the row of holes would have had an unacceptable number of holes - they had to be an even number if the parity check was on even or an odd number if we were checking for odd parity. Both systems were used. If your program is on punched paper tape, then you are even more stuck than if it is on punched cards because you would need to find a teletype terminal that could read that type of punched tape and that may well simply be in a museum!
Once we got to minicomputers, which were normally terminal access, then it is quite possible that your program was stored on a magnetic tape and that will certainly no longer be readable unless somebody had the foresight to keep copying it - for example onto a personal computer connected in place of the terminal - or by generating a listing.
Another thing that has changed is that old requirement that every line in the Fortran code had to conform to that 80-column card format. It was really shorter than 80, as the last 8 columns (or spaces) on the card had to be reserved for a sequence number. That would be useful if the deck of cards was dropped, as I found out from experience!
Nowadays, the lines can be as long as you like, more or less and within reason. You can still use the old convention – I do – and I always label my code files with a .FOR extension. You can use longer lines if you use .F or .F90, or you can define which you want by setting a compiler option. For me, the old layout works well when I print my source code files, which I tend to do on A4 paper, portrait layout. My text editor allows me to prefix each line with a line number, and 72 characters for the statement is quite enough4, thank you.
Older code tends to have a proliferation of statement numbers, and some of the more modern writers will tell you that statement numbers are downright awful. There are things in older Fortran codes that lead to more statement numbers, and some user habits that make them more intrusive. Here are some things in each of the categories.
Firstly, at one time there simply wasn’t the logical IF construct, only the arithmetic IF. Since with the arithmetic IF you need a statement number on the following line as well as on one or two others, then that proliferates statement numbers. Rather interestingly, the ICL 1900 series of mainframes allowed a statement number of 0, which means ‘the next line’, and that removed at least one statement number, but that was a fairly unique extension to whatever standard was in force, almost certainly Fortran 66 but with extensions.
A programmer’s habit that makes statement numbers difficult to follow is for them not to increase as you go through the code. I program with a ‘stride’ of 10, i.e. 10, 20, 30 and so on, and that helps.
Another programmers’ habit is to have a numbered FORMAT statement immediately following the READ or WRITE statement it refers to. Really old Fortran tends to have formats on input as well as output, and where the programmer has used a different number sequence for formats, say 1000, 1001, 1002 and so on, it jumbles up the progression.
I tend to put all my FORMAT statements at the end of each routine, and then their numbering doesn’t get in the way. In fact, I often start output FORMAT statements with a 6 and put them in the 600 plus range as a nod back towards the old convention that the lineprinter was device No. 6! I tend not to use formatted input, but when I did, the format numbers would all start with 5 (so 600, 601, 602 etc, and 500, 501, 502 …). However, don’t be afraid to keep the formatted READ statements and FORMATs. Fixed format READs are a real pain if you are creating an input file in a text editor, but when files are created interactively and saved as formatted output from a program (e.g. from Save in the File menu), then reading them, say from the File menu with Open works just fine.
A final habit that confuses the eye is to number continuation lines 1, 2, 3 etc. Modern Fortran allows you to use symbols, of which ‘&’ is very convenient. If you have a load of & symbols in column 6 in 72-column code, they don’t confuse the eye in the same way. Ultimately, if you also put an & into column 73 of each line that is continued, you have code that works for both fixed and free format!
With few format numbers, advancing periodically through the code with a regular ‘stride’ they function as ‘outdents’, and in my view, don’t have the same deleterious effect that the choice of random statement numbers, intermixed FORMAT numbers and continuation line numbers are likely to do. It’s not that statement numbers are intrinsically bad, it’s that if they are used in certain ways, then they are worse than just bad!
In old Fortran code, comments were only available in one style: lines that began with the letter C in column 1, and while some compilers allowed completely blank lines, most didn’t, and what’s more, programmers eschewed blank lines because they took up valuable space in the ‘deck’ where the number of cards allowed per ‘job’ might be limited. FTN95 doesn’t mind blank lines, and they only take a few bytes each. I think that it is very useful to put blank lines between subprograms in a source code file: I always use three (fewer in the book to save space).
Later version Fortrans also have an alternative comment indicator: the exclamation mark instead of a C in column 1. In fact, the ! symbol can appear just about anywhere, including after the Fortran statement, thereby making an in-line comment. Remember, the Fortran in my way of doing things is in upper case with an inline comment in lower case, so they do stand out as different. I use in-line comments to remind me what variables mean, what DO loops are doing, and so on when I am reading and updating old code and working through what it does. I use lots of inline comments nowadays.
I also tend to divide my subprograms into blocks using blank lines. I used to use blank comments, but complete blanks are marginally better. Then, I put a comment in immediately after a PROGRAM, FUNCTION or SUBROUTINE heading with dashes to underline the header.
I never saw much wrong in terminating nested DO loops on the same statement, and even if that statement was an executable one, such as in:
DO 20 I=1,NI DO 20 J=1,NJ DO 20 K=1,NK 20 A(I, J, K) = ...
Although I would concede that it looks more obvious what is really intended with
DO 20 I=1,NI DO 20 J=1,NJ DO 20 K=1,NK A(I, J, K) = ... 20 CONTINUE
Nowadays, the authorities would prefer you to write it with a lot more statement numbers, as in
DO 40 I = 1, NI DO 30 J = 1, NJ DO 20 K = 1, NK A(I, J, K) = ... 20 CONTINUE 30 CONTINUE 40 CONTINUE
The extra spacing within the statements is my personal preference. Later Fortran versions allow you to do away with the statement number altogether and to write END DO. Personally, I prefer the outdent, but you must program the way that suits you.
DO I = 1, NI DO J = 1, NJ DO K = 1, NK A(I, J, K) = ... END DO END DO END DO
Perhaps using indentation and lower case works for some people. If it works for you then use it.
There are differences between old codes written in Fortran 66 or Fortran 77 relative to later versions of Fortran (as exemplified by FTN95) that do need to be taken into account when you are trying to get an old code to work in the present day. If you are trying to produce a Windows GUI framework in which to run that old program, then you need to get that old program working satisfactorily before you can even begin to integrate it this into any sort of user interface, especially one as complex as Windows.
Should you be developing something completely from scratch, then you will not need to make so many concessions to the style of an old code, but if that is your preference then you can. Alternatively, you are completely at liberty to write your source code in any way that suits you. One of the boasts made by Silverfrost is that you can program Fortran in your way, and so you can, whatever that is.
Moreover, when you are developing from scratch you probably don’t even need to implement any analysis until later in the development of the GUI. Having an old code means that you possibly have to in order to conform to its data structures.
My experience with old codes is that if you set about them with the intent to modify the intrinsic style that the original program used then you run the risk of messing something up so that it no longer works and then you have a big debugging problem that you caused for yourself. A little bit of tidying up makes sense, wholesale deconstruction may well be fixing something that wasn’t broken.
FTN95 has pretty good compile-time diagnostics, generally as good or better than any compiler you ever used before. It also has different compilation modes that can help you to find elusive bugs. I tend not to use them, but if your debugging method is helped, then there are many options available. In the online help file there is a list of compiler options, with the description of each being more than adequate.
FTN95 comes with a debugging option called SDBG with 32 and 64 bit options. I don’t use it, and therefore can only give you very limited advice on using it. The place to find the best guide is not in any files installed on your system, but by going to the Silverfrost website, then choosing to see ‘Online Manual’. There are helpful sections there on the Debugger, and also on using the integrated development environment Plato. Big chunks of the Online Manual simply duplicate what is in FTN95.CHM, but the Debugger and Plato sections are better described in it than anywhere else. The online Manual also has a good section on the Linker, if you want to run that separately, although if you do use Plato it is integrated.
You will have to study the documentation intently to find out about the resource compiler (more on that later) or the Library utility. The main Documentation section on the Silverfrost website contains useful links to what you might think are obsolete manuals for FTN77, but they also contain helpful information on facilities that still exist in FTN95. However, you must ignore references to DBOS, the Weitek co-processor and DBOS graphics!
My own solution to debugging my own code is to write and then test comparatively small sections of code at any time, and to use WRITE statements at frequent intervals to see how things are progressing. With your ClearWin+ program, no routine actually does very much that you can’t keep a check on by seeing how things are presented onscreen, whereas the underlying analysis is much more complicated and does not have that immediate feedback.
Whichever way you do it, the analysis section has to work or your whole program is meaningless, and that’s usually a matter for Fortran programming. If the program ever worked at all, it must be comparatively easy to keep it working even though Fortran has evolved, the old constructs still (mainly) work as they always did.
For someone like me, whose first experiences with Fortran were Fortran 66 and Holleriths, the CHARACTER variables came as a welcome surprise, although mostly I used them as more convenient constants in FORMAT statements or as titles, read in and printed out but never altered. CHARACTERs are a lot more versatile than that! FTN95 has both intrinsic functions, and some custom functions available since FTN77, for manipulating CHARACTER strings.
One thing that I do find particularly useful is concatenation, which is where you join two strings, say STRING1 and STRING2 with the concatenation operator //, as in:
STRING3 = STRING1//STRING2
CHARACTER*(8) NAME NAME = 'BusyBee' IA = WINIO@ ('%ca[This is the caption for a program called'//NAME//']')
The strings to be joined can be variables or constants. The other functions, for which you need to consult a book on FORTRAN and the online help, of especial use are for turning strings to capitals or lower case, removing leading or trailing blanks, or just finding the length of the string.
The rules for continuation of a statement over two or more lines (or cards) have always been simple and simply awful! The use of concatenation helps make a CHARACTER string continued over more than one line rather more readable, especially where that CHARACTER string is the format string in a WINIO@ function call. Here’s a rather contrived example:
IA = WINIO@ ('%ff%2nlEnter the value of load here'// & '%rf&', Value_of_Load)
Remember, however, that if you are using fixed format (card format) in your program that blanks are assumed at the end of every line, and they might matter in continuations. ClearWin+ also has its own ‘continuations’ within WINIO@ calls. One of those is the way that WINIO@ continues to build a window using ‘&’ at the end of each format string to be continued. This is a mechanism that I suggest that you use a lot, because it makes the code less dense (even if it is a bit longer) and therefore easier to follow. If you make an error, FTN95 tells you which continuation the error lies in, so it is worth adding some inline comments periodically so that you don’t have to keep counting – but do it at a relatively late stage in programming of you will have to keep editing as you insert (or delete) WINIO@ calls.
The other continuation scheme is how the menu bar is built up with a number of WINIO@ calls.
3. Russell Watson or Rod Stewart’s “Faith of the Heart” – the former singing the theme to Star Trek: Enterprise.
4. Actually, it is a bit restricting, and I find that now and again, I go over.
FORTRAN and the ART of Windows Programming, Copyright © Eddie Bromhead, 2023.