{"id":14224,"date":"2026-06-12T02:00:00","date_gmt":"2026-06-12T06:00:00","guid":{"rendered":"https:\/\/www.both.org\/?p=14224"},"modified":"2026-05-20T11:35:28","modified_gmt":"2026-05-20T15:35:28","slug":"expand-tabs-in-fortran-77-programs","status":"publish","type":"post","link":"https:\/\/www.both.org\/?p=14224","title":{"rendered":"Expand tabs 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=\"14224\" 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\">When I was an undergraduate physics student, everyone in my program had to learn how to write programs in FORTRAN 77. While Fortran 90 (with the new capitalization) had been standardized just a year or two before, new Fortran 90 compilers were still very expensive, so we used FORTRAN 77 to write data analysis programs.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Old-style FORTRAN uses a particular column-oriented format. This dates back to the original FORTRAN, which was written on <a href=\"https:\/\/en.wikipedia.org\/wiki\/Punched_card\">punched cards<\/a> that stored only 80 columns of data. To make the most of this format, FORTRAN applied a strict column rule:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>C<\/code> or <code>*<\/code> in the first column was a comment line<\/li>\n\n\n\n<li>Columns 1 to 5 were reserved for line labels<\/li>\n\n\n\n<li>Column 6 indicated a continuation from the previous card<\/li>\n\n\n\n<li>Columns 7 to 72 contained program statements<\/li>\n\n\n\n<li>Columns 73 to 80 were ignored; these were used for card sorting machines to put things back into order if you mixed up the stack of cards<\/li>\n<\/ul>\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\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Programming in modern editors<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">By the time I learned FORTRAN 77, no one used punched cards anymore. Instead, we used a plain text editor. But we still needed to keep track of the columns, so we got very good at tapping out six spaces before typing a new program line.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you were lazy like me, you looked for a shortcut. I realized that six spaces was very close to a tab stop, which was every eight columns. In fact, many FORTRAN compilers at that time would replace an initial tab with eight spaces. But using a tab instead of spaces meant you were losing two spaces on a program line. That might not be a big deal for most program statements, but for a program that included very involved calculations, losing two spaces might mean continuing a statement to another line.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I solved this problem for myself by writing a little program that would <a href=\"https:\/\/www.both.org\/?p=14142\">expand tabs to spaces<\/a>. But for my FORTRAN programs, I needed a slight variation: Assume any tab in columns 1 to 6 jumps ahead to column 7, otherwise just add a space.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Writing a program like this is not very difficult in the C programming language. The program starts by counting columns. If it reads a tab as one of the first seven characters on a line, it adds spaces until it reaches column 7. After that, any tab is replaced by a single space.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Because valid FORTRAN program lines should never be longer than 72 columns, the program stops tracking columns at that point. This means the program can use a short variable type to count the columns, since it only needs to count up to 72.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h>\n\nint main()\n{\n    short col = 1;\n    int c;\n\n    while ((c = getchar()) != EOF) {\n        if (c == '\\t') {                                   \/* tab *\/\n            if (col &lt; 7) {\n                while (col &lt; 7) {\n                    putchar(' ');\n                    col++;\n                }\n            }\n            else {\n                putchar(' ');\n                if (col &lt; 73)\n                    col++;\n            }\n        }\n        else {                                             \/* not a tab *\/\n            putchar(c);\n            if (col &lt; 73)\n                col++;\n            if (c == '\\n') {\n                col = 1;\n            }\n        }\n    }\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s save this program as <strong>untab77.c<\/strong> and compile it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ gcc -o untab77 untab77.c<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We can test the program by writing a short FORTRAN 77 source file that uses tabs. This FORTRAN program called <strong>ten.f<\/strong> prints the numbers from one to ten. I\u2019ve used tabs on most lines, and included a comment line that provides a sort of \u201cruler\u201d for columns, up to column 80. We can use the Linux <strong>expand<\/strong> program to expand the tabs to spaces, but it\u2019s important to know where the tabs are so I\u2019ve also used <strong>cat<\/strong> with an option to show the tabs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ expand ten.f\nC2345678901234567890123456789012345678901234567890123456789012345678901234567890\n        PROGRAM LOOP\n        INTEGER I\n      DO        10      I       =       1,      10,     1\n 10     PRINT *,I\n        END\n$ cat --show-tabs ten.f\nC2345678901234567890123456789012345678901234567890123456789012345678901234567890\n^IPROGRAM LOOP\n^IINTEGER I\n      DO^I10^II^I=^I1,^I10,^I1\n 10^IPRINT *,I\n^IEND<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The <strong>untab77<\/strong> program correctly replaces any tabs in the first seven columns with spaces, and any tabs after that with just a single space. This provides a good balance that keeps the program readable:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/untab77 &lt; ten.f\nC2345678901234567890123456789012345678901234567890123456789012345678901234567890\n      PROGRAM LOOP\n      INTEGER I\n      DO 10 I = 1, 10, 1\n 10   PRINT *,I\n      END<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">An improved program<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">One risk when writing FORTRAN programs is that a line might exceed 72 columns. Remember, columns 73 to 80 were ignored, and were reserved for card sorting machines. Since the program is already counting columns, we can easily add a few lines to detect if a program line goes beyond column 72, and print a warning if it does. Here\u2019s an improved version that also reports when text exceeds column 72:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h>\n#include &lt;ctype.h>\n\nint main()\n{\n    short col = 1;\n    int c;\n    size_t line = 1;\n\n    while ((c = getchar()) != EOF) {\n        if (c == '\\t') {                                   \/* tab *\/\n            if (col &lt; 7) {\n                while (col &lt; 7) {\n                    putchar(' ');\n                    col++;\n                }\n            }\n            else {\n                putchar(' ');\n                if (col &lt; 73)\n                    col++;\n            }\n        }\n        else {                                             \/* not a tab *\/\n            if ((col == 73) &amp;&amp; (!isspace(c))) {\n                fprintf(stderr, \"line %zd: extra text beyond column 72\\n\", line);\n                col = 80;\n            }\n\n            putchar(c);\n            if (col &lt; 73)\n                col++;\n            if (c == '\\n') {\n                line++;\n                col = 1;\n            }\n        }\n    }\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If we compile the updated program and run it against the <strong>ten.f<\/strong> test file, we should see it complain about the first line. This line is a comment, so it will be ignored by the compiler anyway, but it\u2019s a good test to see how the program can alert you if your FORTRAN lines get too long:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ gcc -o untab77 untab77.c\n$ .\/untab77 &lt; ten.f\nline 1: extra text beyond column 72\nC2345678901234567890123456789012345678901234567890123456789012345678901234567890\n      PROGRAM LOOP\n      INTEGER I\n      DO 10 I = 1, 10, 1\n 10   PRINT *,I\n      END<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Because the error message is printed using <code>stderr<\/code>, it will only get printed to the user\u2019s terminal. This is important if you use the program as a filter, so you can save the output to a new file. You\u2019ll still see the error message, so you know to check line 1 of the source file in case you need to fix it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/untab77 &lt; ten.f > 10.f\nline 1: extra text beyond column 72<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Writing your own tools<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Being able to create your own tools is a powerful feature of open source systems like Linux. You don\u2019t need to be an expert programmer, you just need to know enough that you can create tools that are useful to you and the work you need to do.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When I was an undergraduate physics student, everyone in my program had to learn how to write programs<\/p>\n","protected":false},"author":33,"featured_media":3096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","footnotes":""},"categories":[798,150],"tags":[400,152],"class_list":["post-14224","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-fortran-77","category-programming","tag-fortran","tag-programming"],"modified_by":"Jim Hall","_links":{"self":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/14224","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/users\/33"}],"replies":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=14224"}],"version-history":[{"count":2,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/14224\/revisions"}],"predecessor-version":[{"id":14226,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/14224\/revisions\/14226"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/media\/3096"}],"wp:attachment":[{"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=14224"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=14224"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=14224"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}