{"id":14329,"date":"2026-07-06T01:00:00","date_gmt":"2026-07-06T05:00:00","guid":{"rendered":"https:\/\/www.both.org\/?p=14329"},"modified":"2026-06-26T15:45:07","modified_gmt":"2026-06-26T19:45:07","slug":"find-invalid-characters-in-fortran-77-programs","status":"publish","type":"post","link":"http:\/\/www.both.org\/?p=14329","title":{"rendered":"Find invalid characters in FORTRAN 77 programs"},"content":{"rendered":"<div class=\"pld-like-dislike-wrap pld-template-1\">\r\n    <div class=\"pld-like-wrap  pld-common-wrap\">\r\n    <a href=\"javascript:void(0)\" class=\"pld-like-trigger pld-like-dislike-trigger  \" title=\"\" data-post-id=\"14329\" data-trigger-type=\"like\" data-restriction=\"cookie\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-up\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-like-count-wrap pld-count-wrap\">    <\/span>\r\n<\/div><\/div>\n<p class=\"wp-block-paragraph\">My undergraduate degree was in physics, and at the time, every physics student at my university had know how to write FORTRAN 77 programs. Not every lab could be analyzed by a spreadsheet or with a linear regression; sometimes, you needed to write your own data analysis program. In a few upper-level labs, we had to simulate a complex equation of motion and perform numerical analysis with a FORTRAN 77 program.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The FORTRAN programming language has advanced considerably since then, although I admit I haven&#8217;t followed its evolution since then. I know that the language changed in 1990 with Fortran 90 (which also changed the capitalization of the name). Fortran 90 and later versions eliminated the column-limited nature of old-style FORTRAN.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But old-style FORTRAN has enjoyed a certain popularity as more people discover <em>retro-computing<\/em>, and specifically <em>retro-programming<\/em> with FORTRAN 77. For example, you can compile FORTRAN 77 programs using the GNU <strong>gfortran<\/strong> compiler, which is part of the GNU Compiler Collection (GCC). Or you can boot into FreeDOS and install the Open Watcom FORTRAN 77 from the Bonus CD.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Allowed characters<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Old-style FORTRAN was created at a time when computers read programs from <em>punched cards<\/em>. This added a limitation to how you could write programs: Each card was 80 columns, although columns 73 to 80 were reserved for card-sorting machines. The other columns had specific meaning: <code>C<\/code> or <code>*<\/code> in column 1 was a comment, numbers in columns 1 to 5 were line labels, a character in column 6 continued from the previous line, and columns 7 to 72 were for program statements.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"767\" height=\"345\" src=\"http:\/\/www.both.org\/wp-content\/uploads\/2026\/04\/f77card.png\" alt=\"Fortran punch card showing a single Format statement\" class=\"wp-image-14102\"\/><figcaption class=\"wp-element-caption\">A punched card with a FORTRAN 77 statement<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">As a FORTRAN 77 programmer, I got pretty good at tapping out 6 spaces when starting a new program line. But in an earlier article, I wrote about how to <a href=\"https:\/\/www.both.org\/?p=14224\">expand tabs in a FORTRAN 77 program<\/a> so you could type a tab instead, and let a program convert the tab to the right number of spaces for you.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Another limitation was that punched cards could only represent a limited set of characters. The FORTRAN 77 specification (ANSI X3.9-1978) specifies the allowed characters as: space, the uppercase letters <code>A<\/code> to <code>Z<\/code>, the numbers <code>0<\/code> to <code>9<\/code>, the math symbols <code>=<\/code> <code>+<\/code> <code>-<\/code> <code>*<\/code> <code>\/<\/code> <code>(<\/code> <code>)<\/code>, and the punctuation symbols dollar (<code>$<\/code>) quote (<code>'<\/code>) colon (<code>:<\/code>) comma (<code>,<\/code>) and period (<code>.<\/code>).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Lowercase to uppercase<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">But typing in all-uppercase is tiring to look at. As a university student who was also learning C programming at the time, I preferred typing my programs in all-lowercase.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Converting to uppercase is very easy with the Unix <strong>tr<\/strong> command. In the standard usage, <strong>tr<\/strong> takes two character sets: the range of characters to convert <em>from<\/em>, and the range to convert <em>to<\/em>. For example, to convert lowercase to uppercase, you can use <strong>tr<\/strong> this way:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ tr a-z A-Z<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s see that in action by using the <strong>echo<\/strong> command to print a short message that <strong>tr<\/strong> will convert to uppercase:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ echo Fortran | tr a-z A-Z\nFORTRAN<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Converting from lowercase to uppercase with <strong>tr<\/strong> was a handy feature, especially when combined with the <strong>untab77<\/strong> program from the <a href=\"https:\/\/www.both.org\/?p=14224\">earlier article<\/a>. I could write FORTRAN 77 programs in all-lowercase, using leading tabs, and let the computer convert my source code to an acceptable format that the compiler would recognize. In a typical example, I might write my program under one filename, then use the <strong>untab77<\/strong> and <strong>tr<\/strong> programs to convert the text and save it under a new filename, which I would then compile.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Of course, Linux didn&#8217;t have a FORTRAN 77 compiler when I was an undergraduate student in the early 1990s, so I instead used the <strong>f2c<\/strong> program. This converted <a href=\"https:\/\/www.both.org\/?p=14140\">FORTRAN 77 into C<\/a>, which could be compiled and linked with the <strong>f2c<\/strong> library:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ untab77 &lt; analyze.f | tr a-z A-Z &gt; t.f\n$ f2c t.f\nt.f:\n   MAIN loop:\n$ gcc -o analyze t.c -lf2c -lm<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Finding invalid characters<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">FORTRAN had a limited character set of letters, numbers, spaces, and certain math and punctuation characters. While some FORTRAN compilers allowed other characters for special purposes, these were only <em>extensions<\/em> to the language and not guaranteed to be supported everywhere. For example, FORTRAN 77 on the VAX used exclamation (<code>!<\/code>) to provide an <em>inline comment<\/em> after a program statement. This was a popular extension, but not every FORTRAN 77 compiler recognized this.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I only wanted to write <em>valid<\/em> and <em>portable<\/em> FORTRAN 77 programs, so I created a program that would warn me if my source code contained characters not recognized by the ANSI X3.9-1978 standard. Since this program evaluated input one character at a time, I extended the program to convert lowercase to uppercase at the same time, saving me the extra step to use <strong>tr<\/strong> to do that.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To write this program, we first need to write a function that recognizes if a character is part of the ANSI X3.9-1978 allowed character set. This function evaluates a single character (<code>c<\/code>) to see if it is an uppercase letter, a number, or one of the allowed math or punctuation symbols:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int charset77(int c)\n{\n    \/* is this character part of the F77 char set? *\/\n\n    \/* see 3-1 in ANSI X3.9-1978 *\/\n    \/* A-Z 0-9 space = + - * \/ ( ) , . $ ' : *\/\n\n    \/* A-Z *\/\n    if ((c &gt;= 'A') &amp;&amp; (c &lt;= 'Z')) { return 1; }\n\n    \/* 0-9 *\/\n    if ((c &gt;= '0') &amp;&amp; (c &lt;= '9')) { return 1; }\n\n    \/* ' ( ) * + , - . \/ *\/\n    if ((c &gt;= '\\'') &amp;&amp; (c &lt;= '\/')) { return 1; }\n\n    \/* space = $ : *\/\n    if ((c == ' ') || (c == '=') || (c == '$') || (c == ':')) { return 1; }\n\n    \/* certain other control chars are allowed too: *\/\n\n    if (c == '\\n') { return 1; }\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The function takes a &#8220;step-wise&#8221; approach, and evaluates the input character against the ranges of allowed characters in separate &#8220;passes.&#8221; If the character is an uppercase letter, the function returns <strong>1<\/strong> to indicate a <em>true<\/em> value. And the same if the character is a number or one of the other allowed math and punctuation characters.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">At the end, if it could not match one of the allowed characters, the function returns <strong>0<\/strong> to indicate a <em>false<\/em> value. These days, you might write the C program to include <code>&lt;stdbool.h&gt;<\/code> and return a <code>true<\/code> or <code>false<\/code> value, but C programming in the early 1990s didn&#8217;t have these standard Boolean values; using zero for <em>false<\/em> and any other value for <em>true<\/em> was typical.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With this function, we can now write our main program that converts input characters from lowercase to uppercase, and detects invalid characters at the same time. This program is a very simple one, and only reads from standard <em>input<\/em> (using <code>getchar<\/code>) and prints to standard <em>output<\/em> (using <code>putchar<\/code>). Error messages are printed on standard <em>error<\/em>, so warnings will not be saved if you use shell redirection (like <code>&gt;<\/code>) to send the output to a file.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int main()\n{\n    int c;\n\n    \/* uppercase everything *\/\n\n    while ((c = getchar()) != EOF) {\n        if (islower(c)) {\n            putchar(toupper(c));\n        }\n        else {\n            putchar(c);\n\n            if (!charset77(c)) {\n                fprintf(stderr, \"'%c' invalid character\\n\", c);\n            }\n        }\n    }\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the character is a lowercase letter (the <code>islower<\/code> function can test this very easily) the function simply prints it as an uppercase letter (using the <code>toupper<\/code> standard C library function). Otherwise, the function prints the character, and evaluates if it is part of the allowed FORTRAN 77 character set (using the <code>charset77<\/code> function, from above).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s put it all together into a single C program file, called <code>upper77.c<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n#include &lt;ctype.h&gt;\n\nint charset77(int c)\n{\n    \/* is this character part of the F77 char set? *\/\n\n    \/* see 3-1 in ANSI X3.9-1978 *\/\n    \/* A-Z 0-9 space = + - * \/ ( ) , . $ ' : *\/\n\n    \/* A-Z *\/\n    if ((c &gt;= 'A') &amp;&amp; (c &lt;= 'Z')) {\n        return 1;\n    }\n\n    \/* 0-9 *\/\n    if ((c &gt;= '0') &amp;&amp; (c &lt;= '9')) {\n        return 1;\n    }\n\n    \/* ' ( ) * + , - . \/ *\/\n    if ((c &gt;= '\\'') &amp;&amp; (c &lt;= '\/')) {\n        return 1;\n    }\n\n    \/* space = $ : *\/\n    if ((c == ' ') || (c == '=') || (c == '$') || (c == ':')) {\n        return 1;\n    }\n\n    \/* certain other control chars are allowed too: *\/\n\n    if (c == '\\n') {\n        return 1;\n    }\n\n    return 0;\n}\n\nint main()\n{\n    int c;\n\n    \/* uppercase everything *\/\n\n    while ((c = getchar()) != EOF) {\n        if (islower(c)) {\n            putchar(toupper(c));\n        }\n        else {\n            putchar(c);\n\n            if (!charset77(c)) {\n                fprintf(stderr, \"'%c' invalid character\\n\", c);\n            }\n        }\n    }\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You can compile the program using the GNU C Compiler:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ gcc -o upper77 upper77.c<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Find invalid characters<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s see this program in action by testing it with a simple FORTRAN 77 program that prints the numbers from 1 to 10, plus the <em>square<\/em> of that value (1^2 = 1, 2^2 = 4, and so on). I&#8217;ve written this in all-lowercase, using tabs, like I might have done in the 1990s. Note that we can always expand the tabs using the <strong>untab77<\/strong> program from the <a href=\"https:\/\/www.both.org\/?p=14224\">other article<\/a>, and convert from lowercase to uppercase using the new <strong>upper77<\/strong> program:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ cat --show-tabs square.f\nc print the numbers 1 to 10, and its square value (n^2)\n^Iprogram square\n^Iinteger n\n^Ido 10 n=1,10,1\n10^Iprint *,n,n**2\n^Iend\n\n$ untab77 &lt; square.f\nc print the numbers 1 to 10, and its square value (n^2)\n      program square\n      integer n\n      do 10 n=1,10,1\n10    print *,n,n**2\n      end<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now we can use the <strong>upper77<\/strong> program to convert this to uppercase, and use shell redirection (with <code>><\/code>) to save the output to a new file. Because the caret (<code>^<\/code>) is not part of the FORTRAN 77 allowed character set, <strong>upper77<\/strong> will also print a warning. Fortunately, this is part of a comment, and will be ignored anyway.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ untab77 &lt; square.f | upper77 &gt; t.f\n'^' invalid character\n\n$ cat t.f\nC PRINT THE NUMBERS 1 TO 10, AND ITS SQUARE VALUE (N^2)\n      PROGRAM SQUARE\n      INTEGER N\n      DO 10 N=1,10,1\n10    PRINT *,N,N**2\n      END<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Finally, we can compile the program with the FORTRAN 77 compiler. Let&#8217;s do it like the early 1990s, using the <strong>f2c<\/strong> utility to convert from FORTRAN to C, then compiling that C program using the GNU C Compiler:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ f2c t.f\nt.f:\n   MAIN square:\n$ gcc -o square t.c -lf2c -lm<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The result is a valid program that prints the values from 1 to 10, plus the square of each value: 1 to 100.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/square\n 1 1\n 2 4\n 3 9\n 4 16\n 5 25\n 6 36\n 7 49\n 8 64\n 9 81\n 10 100<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Writing these little tools made the command line more useful to me. With a few command line tools, I could write FORTRAN 77 programs the way that felt more natural to me (using lowercase and tabs) and convert them to the proper format when I compiled the program. Being able to create your own tools is a powerful feature of open source operating systems. You don&#8217;t need to be an expert programmer, you just need to know enough that you can create tools that let you work the way you want to.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Combine untab77 and f2c with this new program, and write FORTRAN 77 the way you want to.<\/p>\n","protected":false},"author":33,"featured_media":3545,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","footnotes":"","_members_access_role":[],"_members_access_error":""},"categories":[798,150],"tags":[522,152],"class_list":["post-14329","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-fortran-77","category-programming","tag-fortran77","tag-programming"],"modified_by":"Jim Hall","_links":{"self":[{"href":"http:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/14329","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/users\/33"}],"replies":[{"embeddable":true,"href":"http:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=14329"}],"version-history":[{"count":11,"href":"http:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/14329\/revisions"}],"predecessor-version":[{"id":14341,"href":"http:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/14329\/revisions\/14341"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/media\/3545"}],"wp:attachment":[{"href":"http:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=14329"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=14329"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=14329"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}