Index: src/proc-db/naca/naca456.c
===================================================================
--- src/proc-db/naca/naca456.c	(revision 63769)
+++ src/proc-db/naca/naca456.c	(working copy)
@@ -38,14 +38,584 @@
  *
  */
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+
 #include "naca.h"
+#include "bu/malloc.h"
+#include "bu/str.h"
 
+/* Function forward-declarations */
+static void ReadDataAndMakeAirfoils(void);
+static void PrintArraysNumbered(FILE *efu, struct fortran_array *x, struct fortran_array *y,
+				struct fortran_array *a, struct fortran_array *b, struct fortran_array *c, struct fortran_array *d);
+static void ScaleAirfoil(fastf_t scale, fastf_t xOrigin, fastf_t yOrigin,
+			 struct fortran_array *xupper, struct fortran_array *yupper, struct fortran_array *xlower, struct fortran_array *ylower);
+
+/* Global variables */
+static FILE *IN, *OUT, *DBG, *GNU;
+static char *dateTimeStr;
+
+const char *VERSION = "1.1 (7 November 2010)";
+
 int
-main(int argc, const char **argv)
+main(int UNUSED(argc), const char **UNUSED(argv))
 {
+    const char *FAREWELL = "End of naca456.  Files naca.out, naca.gnu and naca.dbg created.";
+/*    Welcome();*/
+    ReadDataAndMakeAirfoils();
+    printf("%s", FAREWELL);
     return 0;
 }
 
+/**
+ * Count the number of elements of an array that have been input thru
+ * a NAMELIST call.  This is to save the user from the error-prone
+ * process of counting the number of entries in a list.  The array is
+ * preset to a very negative value that no one would ever use for real
+ * data.  This routine simply searches for the first entry in the
+ * array that still has this value.
+ *
+ * @param[in] preset the value that was originally placed in each
+ * @param[in] a array to be counted
+ */
+static int
+CountInputArray(fastf_t preset, struct fortran_array *a)
+{
+    int k, n;
+    n = SIZE(a);
+
+    for (k = 1; k <= n; k++) {
+	if (INDEX(a, k) <= preset) {
+	    break;
+	}
+    }
+    n = k - 1; /* failed on k; k - 1 was the last good one */
+    return n;
+}
+
+/**
+ * Print a description of the mean line in the printed output
+ */
+static void
+DescribeMeanLine(FILE *efu, const char *camber, fastf_t cmax, fastf_t xmaxc, fastf_t a, fastf_t cl)
+{
+    const char *FMT2 = "Two digit mean line,  max camber=%6.3f  x of max. camber=%6.3f\n";
+    const char *FMT3 = "Three digit mean line, cl=%7.4f  x of max. camber=%6.3f\n";
+    const char *FMT3R = "Three digit mean line, cl=%7.4f  x of max. camber=%6.3f\n";
+    const char *FMT6 = "Six-series mean line, a=%7.4f   cl=%7.4f\n";
+    const char *FMT6M = "Six-series mean line (modified), cl=%7.4f  (a=0.8 always for 6M)\n";
+
+    switch(camber[0]) {
+    case '0':
+	fprintf(efu, "No camber, symmetrical section\n");
+	break;
+    case '2':
+	fprintf(efu, FMT2, cmax, xmaxc);
+	break;
+    case '3':
+	if (!bu_strcasecmp(camber, "3")) {
+	    fprintf(efu, FMT3, cl, xmaxc);
+	} else if (!bu_strcasecmp(camber, "3R")) {
+	    fprintf(efu, FMT3R, cl, xmaxc);
+	}
+	break;
+    case '6':
+	if (!bu_strcasecmp(camber, "6")) {
+	    fprintf(efu, FMT6, a, cl);
+	} else if (!bu_strcasecmp(camber, "6M")) {
+	    fprintf(efu, FMT6M, cl);
+	}
+	break;
+    }
+}
+
+/**
+ * Print a description of the profile in the printed output
+ */
+static void
+DescribeProfile(FILE *efu, const char *profile, fastf_t toc, fastf_t leIndex, fastf_t xmaxt)
+{
+    const char *FMT4 = "Four-digit profile, t/c=%7.4f";
+    const char *FMT4M = "Four-digit profile, t/c=%7.4f\n   l.e. index=%7.4f,   x of max. thickness=%7.4f";
+    const char *FMT6 = "Six-series profile, family= %s   t/c=%7.4f";
+
+    if (!bu_strcasecmp(profile, "4")) {
+	fprintf(efu, FMT4, toc);
+    } else if (!bu_strcasecmp(profile, "4M")) {
+	fprintf(efu, FMT4M, toc, leIndex, xmaxt);
+    } else {
+	fprintf(efu, FMT6, profile, toc);
+    }
+}
+
+/**
+ * Return a string with the current date and time.  You can change the
+ * first I2.2 below to I2 if you don't like a leading zero on early
+ * morning times, i.e., 6:45 instead of 06:45.
+ */
+static char *
+GetDateTimeStr(void)
+{
+    const char MONTH[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
+    char *str = (char *)bu_malloc(sizeof(char) * 16, "GetDateTimeStr");
+    time_t current_time_t = time(NULL);
+    struct tm *current_time = gmtime(&current_time_t);
+    char *current_month = (char *)bu_malloc(sizeof(char) * 4, "GetDateTimeStr");
+    bu_strlcpy(current_month, MONTH + current_time->tm_mon * 3, 4);
+
+    sprintf(str, "%2.2d:%2.2d%3.3d%3s%4d", current_time->tm_hour, current_time->tm_min, current_time->tm_mday, current_month, current_time->tm_year);
+    return str;
+}
+
+/**
+ * Read data from the input file and define an airfoil.
+ */
+static void
+ReadDataAndMakeAirfoils(void)
+{
+
+    int i;
+    int len;
+    char *in;
+
+    fastf_t a; /* chordwise extent of constant loading */
+    char *camber = "0"; /* Camber line (2-digit or 3-digit;
+		 = '0' no camber
+		 = '2' 2-digit mean line
+		 = '3' 3-digit mean line
+		 = '3R' 3-digit reflex mean line
+		 = '6' 6-series mean line
+		 = '6M' 6-series (modified) mean line */
+    fastf_t chord = 1.0; /* model chord length used for listing ordinates */
+    fastf_t cl; /* design lift coefficient of the camber line
+		   applies to 3-digit, 3-digit-reflex and
+		   6-series camber lines */
+    fastf_t cmax = 0.04; /* maximum camber ordinate-to-chord ratio */
+    int denCode = 1; /* =0 if specified by the user
+			=1 for coarse output
+			=2 for fine output
+			=3 for very fine output */
+    int errCode;
+    fastf_t leIndex = 6.0; /* leading-edge index (4-digit modified) */
+    char name[80]; /* title desired on output */
+    int nTable = 1; /* size of xTable (only used if denCode = 0) */
+    const fastf_t PRESET = -1e20;
+    const char *profile  = "4"; /* NACA airfoil family
+			 = '4' four digit profile
+			 = '4M' modified-four-digit profile
+			 = '63' 63 series profile
+			 = '64' 64 series profile
+			 = '65' 65 series profile
+			 = '66' 66 series profile
+			 = '67' 67 series profile
+			 = '63A' 63A series profile
+			 = '64A' 64A series profile
+			 = '65A' 65A series profile */
+    fastf_t toc = 0.1; /* thickness-chord ratio of airfoil. */
+    fastf_t xmaxc = 0.4; /* location of maximum camber position
+			    used for 2-,3- and 3-digit-reflex mean lines */
+    fastf_t xmaxt = 0.3; /* location of maximum camber position
+			    used for 2-,3- and 3-digit-reflex mean lines */
+    fastf_t xOrigin = 0.0, yOrigin = 0.0; /* leading edge point */
+    double C_xTable[1000];
+    struct fortran_array *xTable;
+
+    struct fortran_array *x, *ymean, *ymeanp, *yt, *ytp;
+    fastf_t yMeanMax = -INFINITY;
+    struct fortran_array *xUpper, *xLower, *yUpper, *yLower;
+    struct fortran_array *yu, *yl, *yup, *ylp;
+
+    const char *TITLE1 = "COORDINATES OF NACA AIRFOILS";
+    const char *TITLE2 = "SYMMETRICAL AIRFOIL DEFINITION";
+    const char *TITLE3 = "x         y        dy/dx";
+    const char *TITLE4 = "THICKNESS          MEAN LINE";
+    const char *TITLE5 = "x         y      dy/dx         y      dy/dx";
+    const char *TITLE6 = "COMBINED THICKNESS AND CAMBER";
+    const char *TITLE7 = "xupper    yupper    xlower    ylower";
+    const char *TITLE8 = "INTERPOLATED COORDINATES";
+    const char *TITLE9 = "x      yupper   ylower";
+    const char *TITLE10 = "SCALED AND TRANSLATED AIRFOIL";
+    const char *FMT1 = "Scaled chord length=%12.5f\n";
+    const char *FMT2 = "   leading edge at x=%12.5f   y=%12.5f\n";
+
+    NL_ENTRY_DECLARE7(a, camber, chord, cl, cmax, denCode, leIndex);
+    NL_ENTRY_DECLARE7(name, profile, toc, xmaxc, xmaxt, xOrigin, yOrigin);
+    NL_ARRAY_DECLARE(C_xTable);
+    NAMELIST(nl, 15);
+
+    NL_ENTRY(nl, 0, a, scan_fastf_t, "%lf");
+    NL_ENTRY(nl, 1, camber, scan_string, NULL);
+    NL_ENTRY(nl, 2, chord, scan_fastf_t, NULL);
+    NL_ENTRY(nl, 3, cl, scan_fastf_t, NULL);
+    NL_ENTRY(nl, 4, cmax, scan_fastf_t, NULL);
+    NL_ENTRY(nl, 5, denCode, scan_single_value, "%d");
+    NL_ENTRY(nl, 6, leIndex, scan_fastf_t, NULL);
+    NL_ENTRY(nl, 7, name, scan_string, NULL);
+    NL_ENTRY(nl, 8, profile, scan_string, NULL);
+    NL_ENTRY(nl, 9, toc, scan_fastf_t, NULL);
+    NL_ENTRY(nl, 10, xmaxc, scan_fastf_t, NULL);
+    NL_ENTRY(nl, 11, xmaxt, scan_fastf_t, NULL);
+    NL_ENTRY(nl, 12, xOrigin, scan_fastf_t, NULL);
+    NL_ENTRY(nl, 13, yOrigin, scan_fastf_t, NULL);
+    NL_ARRAY_ENTRY(nl, 14, C_xTable, 1000, sizeof(double), scan_fastf_t, NULL);
+
+    for (i = 0; i < 1000; i++) {
+	C_xTable[i] = PRESET;
+    }
+
+    fseek(IN, 0L, SEEK_END);
+    len = ftell(IN);
+    fseek(IN, 0L, SEEK_SET);
+    in = (char *)bu_malloc(len, "ReadDataAndMakeAirfoils");
+    fread(in, sizeof(char), len, IN);
+
+    errCode = read_namelist(in, "NACA", &nl);
+    if (errCode < 1) {
+	printf("End of file reading input\n");
+	fprintf(DBG, "End of file reading input\n");
+	fprintf(OUT, "End of file reading input\n");
+	exit(1);
+    }
+    fprintf(DBG, "Namelist read successfully\n");
+    fprintf(DBG, " %s", name);
+
+    if (denCode == 0) {
+	C2F(xTable, C_xTable, 1000);
+	nTable = CountInputArray(PRESET, xTable);
+    } else {
+	ALLOCATE(xTable, 1000);
+	LoadX(denCode, &nTable, xTable);
+    }
+
+    fprintf(DBG, "Allocating x,ymean,... with denCode=%d\n", denCode);
+    ALLOCATE(x, nTable);
+    ALLOCATE(ymean, nTable);
+    ALLOCATE(ymeanp, nTable);
+    ALLOCATE(yt, nTable);
+    ALLOCATE(ytp, nTable);
+    ALLOCATE(xUpper, nTable);
+    ALLOCATE(yUpper, nTable);
+    ALLOCATE(xLower, nTable);
+    ALLOCATE(yLower, nTable);
+
+    SLICE(x, xTable, 1, nTable);
+    fprintf(DBG, "nTable is now %d\n", nTable);
+
+    fprintf(DBG, "THICKNESS DEFINITION\n");
+    if (!bu_strcasecmp(profile, "4")) {
+	fprintf(DBG, "Four-digit profile\n");
+	Thickness4(toc, x, yt, ytp, NULL);
+    } else if (!bu_strcasecmp(profile, "4M")) {
+	fprintf(DBG, "Four-digit modified profile %f %f\n", leIndex, xmaxt);
+	Thickness4M(toc, leIndex, xmaxt, x, yt, ytp, NULL);
+    } else if (!bu_strcasecmp(profile, "63")) {
+	fprintf(DBG, "63-series profile\n");
+	Thickness6(1, toc, x, yt, ytp, NULL);
+    } else if (!bu_strcasecmp(profile, "64")) {
+	fprintf(DBG, "64-series profile\n");
+	Thickness6(2, toc, x, yt, ytp, NULL);
+    } else if (!bu_strcasecmp(profile, "65")) {
+	fprintf(DBG, "65-series profile\n");
+	Thickness6(3, toc, x, yt, ytp, NULL);
+    } else if (!bu_strcasecmp(profile, "66")) {
+	fprintf(DBG, "66-series profile\n");
+	Thickness6(4, toc, x, yt, ytp, NULL);
+    } else if (!bu_strcasecmp(profile, "67")) {
+	fprintf(DBG, "67-series profile\n");
+	Thickness6(5, toc, x, yt, ytp, NULL);
+    } else if (!bu_strcasecmp(profile, "63A")) {
+	fprintf(DBG, "63A-series profile\n");
+	Thickness6(6, toc, x, yt, ytp, NULL);
+    } else if (!bu_strcasecmp(profile, "64A")) {
+	fprintf(DBG, "64A-series profile\n");
+	Thickness6(7, toc, x, yt, ytp, NULL);
+    } else if (!bu_strcasecmp(profile, "65A")) {
+	fprintf(DBG, "65A-series profile\n");
+	Thickness6(8, toc, x, yt, ytp, NULL);
+    } else {
+	printf("Not a valid profile: %s", profile);
+	fprintf(DBG, "Not a valid profile: %s", profile);
+	exit(1);
+    }
+
+    fprintf(DBG, "          x         y        dy/dx\n");
+    PrintArraysNumbered(DBG, x, yt, ytp, NULL, NULL, NULL);
+    if (!bu_strcasecmp(camber, "0")) {
+	fprintf(DBG, "No camber\n");
+	for (i = 1; i <= nTable; i++) {
+	    INDEX(ymean, i) = 0.0;
+	    INDEX(ymeanp, i) = 0.0;
+	}
+    } else if (!bu_strcasecmp(camber, "2")) {
+	fprintf(DBG, "Two digit mean line %f %f\n", xmaxc, cmax);
+	MeanLine2(cmax, xmaxc, x, ymean, ymeanp);
+    } else if (!bu_strcasecmp(camber, "3")) {
+	fprintf(DBG, "Three digit camber line\n");
+	MeanLine3(cl, xmaxc, x, ymean, ymeanp);
+    } else if (!bu_strcasecmp(camber, "3R")) {
+	fprintf(DBG, "Three digit (reflex) camber line\n");
+	MeanLine3Reflex(cl, xmaxc, x, ymean, ymeanp);
+    } else if (!bu_strcasecmp(camber, "6")) {
+	fprintf(DBG, "6-series camber line\n");
+	MeanLine6(a, cl, x, ymean, ymeanp);
+    } else if (!bu_strcasecmp(camber, "6A") || !bu_strcasecmp(camber, "6M")) {
+	fprintf(DBG, "6A-series camber line\n");
+	MeanLine6M(cl, x, ymean, ymeanp);
+    } else {
+	printf("Not a valid mean line: %s\n", camber);
+	fprintf(DBG, "Not a valid mean line: %s\n", camber);
+    }
+
+    for (i = 1; i <= nTable; i++) {
+	struct fortran_array *minus_yt;
+	ALLOCATE(minus_yt, nTable);
+	VSCALEN(F2C(minus_yt), F2C(yt), -1, nTable);
+	V_MAX(yMeanMax, INDEX(ymean, i));
+	fprintf(OUT, "%s\n", name);
+	DescribeProfile(OUT, profile, toc, leIndex, xmaxt);
+	DescribeMeanLine(OUT, camber, cmax, xmaxc, a, cl);
+	fprintf(OUT, "%s\n", TITLE2);
+	fprintf(OUT, "%s\n", TITLE3);
+	PrintArraysNumbered(OUT, x, yt, ytp, NULL, NULL, NULL);
+	ScaleAirfoil(chord, xOrigin, yOrigin, x, yt, x, minus_yt);
+	fprintf(OUT, "End of output for symmetrical airfoil\n");
+	return;
+    }
+
+    fprintf(DBG, "MEAN LINE DEFINITION\n");
+    fprintf(DBG, "         x          y        dy/dx\n");
+    PrintArraysNumbered(DBG, x, ymean, ymeanp, NULL, NULL, NULL);
+    fprintf(OUT, " \n");
+    fprintf(OUT, "%s\n", name);
+    DescribeProfile(OUT, profile, toc, leIndex, xmaxt);
+    DescribeMeanLine(OUT, camber, cmax, xmaxc, a, cl);
+    fprintf(OUT, " \n");
+
+    fprintf(OUT, "                       %s\n", TITLE4);
+    fprintf(OUT, "            %s\n", TITLE5);
+    PrintArraysNumbered(OUT, x, yt, ytp, ymean, ymeanp, NULL);
+    CombineThicknessAndCamber(x, yt, ymean, ymeanp, xUpper, yUpper, xLower, yLower);
+    fprintf(DBG, "%s\n", TITLE6);
+    fprintf(DBG, "        %s\n", TITLE7);
+    PrintArraysNumbered(DBG, xUpper, yUpper, xLower, yLower, NULL, NULL);
+    fprintf(OUT, "\f\n");
+    /* dateTimeStr should start in the 40th column, so there need to
+     * be 39 chars printed; TITLE1 contains 28, so there should be 11
+     * left, which is why the length modifier for the empty string is
+     * 11.
+     */
+    fprintf(OUT, "%s%11s%s\n", TITLE1, "", dateTimeStr);
+    fprintf(OUT, "%s\n", name);
+    fprintf(OUT, "%s\n", TITLE6);
+    fprintf(OUT, "            %s\n", TITLE7);
+
+    PrintArraysNumbered(OUT, xUpper, yUpper, xLower, yLower, NULL, NULL);
+    ALLOCATE(yu, nTable);
+    ALLOCATE(yl, nTable);
+    ALLOCATE(yup, nTable);
+    ALLOCATE(ylp, nTable);
+    InterpolateUpperAndLower(xUpper, yUpper, xLower, yLower, x, yu, yl, yup, ylp);
+
+    fprintf(OUT, "\f\n");
+    /* See the comment above for an explanation of the 11. */
+    fprintf(OUT, "%s%11s%s\n", TITLE1, "", dateTimeStr);
+    fprintf(OUT, "%s\n", name);
+    fprintf(OUT, "%s\n", TITLE8);
+    fprintf(OUT, "            %s\n", TITLE9);
+
+    PrintArraysNumbered(DBG, x, yu, yup, yl, ylp, NULL);
+    PrintArraysNumbered(OUT, x, yu, yl, NULL, NULL, NULL);
+
+    if (!ZERO(xOrigin) || !ZERO(yOrigin) || fabs(chord - 1.0) > 1e-6) {
+	fprintf(OUT, "\f\n");
+	/* See the comment above for an explanation of the 11. */
+	fprintf(OUT, "%s%11s%s\n", TITLE1, "", dateTimeStr);
+	fprintf(OUT, "%s\n", name);
+	fprintf(OUT, FMT1, chord);
+	fprintf(OUT, FMT2, xOrigin, yOrigin);
+	fprintf(OUT, "%s\n", TITLE10);
+	fprintf(OUT, "         %s\n", TITLE7);
+    }
+    ScaleAirfoil(chord, xOrigin, yOrigin, x, yu, x, yl);
+
+    DEALLOCATE(ylp);
+    DEALLOCATE(yup);
+    DEALLOCATE(yl);
+    DEALLOCATE(yu);
+    DEALLOCATE(yLower);
+    DEALLOCATE(xLower);
+    DEALLOCATE(yUpper);
+    DEALLOCATE(xUpper);
+    DEALLOCATE(ytp);
+    DEALLOCATE(yt);
+    DEALLOCATE(ymeanp);
+    DEALLOCATE(ymean);
+    DEALLOCATE(xTable);
+
+    fprintf(OUT, "End of output for cambered airfoil\n");
+}
+
+static char *
+Trim(char *s)
+{
+    int j;
+    char c;
+
+    /* Move input past any leading spaces */
+    while (isspace(*s++)) {}
+    s--;
+
+    /* Add a terminating null after the last non-space non-null byte */
+    for (j = strlen(s); isspace(c = s[j]) || c == '\0'; j--) {}
+    s[j+1] = '\0';
+
+    return s;
+}
+
+/**
+ * Print arrays, neatly formatted.  X and Y are always printed.  The
+ * next 4 optional variables are printed when present.
+ */
+static void
+PrintArrays(FILE *efu, struct fortran_array *x, struct fortran_array *y,
+	    struct fortran_array *a, struct fortran_array *b, struct fortran_array *c, struct fortran_array *d)
+{
+    char *buffer = (char *)bu_malloc(80, "PrintArrays");
+    int k, j;
+    char ch;
+    VSETALLN(buffer, 0, 80);
+    for (k = 1; k <= SIZE(x); k++) {
+	snprintf(buffer, 20, "%10.6f%10.6f", INDEX(x, k), INDEX(y, k));
+	if (a) { snprintf(buffer + 20, 10, "%10.6f", INDEX(a, k)); }
+	if (b) { snprintf(buffer + 30, 10, "%10.6f", INDEX(b, k)); }
+	if (c) { snprintf(buffer + 40, 10, "%10.6f", INDEX(c, k)); }
+	if (d) { snprintf(buffer + 50, 10, "%10.6f", INDEX(d, k)); }
+	for (j = 79; isspace(ch = buffer[j]) || ch == '\0'; j--) {}
+	buffer[j + 1] = '\0';
+	fprintf(efu, "%s\n", buffer);
+    }
+}
+
+/**
+ * Print arrays, neatly formatted.  X and Y are always printed.  The
+ * next 4 optional variables are printed when present.
+ */
+static void
+PrintArraysNumbered(FILE *efu, struct fortran_array *x, struct fortran_array *y,
+		    struct fortran_array *a, struct fortran_array *b, struct fortran_array *c, struct fortran_array *d)
+{
+    char *buffer = (char *)bu_malloc(80, "PrintArraysNumbered");
+    int k, j;
+    char ch;
+    VSETALLN(buffer, 0, 80);
+    for (k = 1; k <= SIZE(x); k++) {
+	snprintf(buffer, 5, "%5d", k);
+	snprintf(buffer + 5, 20, "%10.6f%10.6f", INDEX(x, k), INDEX(y, k));
+	if (a) { snprintf(buffer + 25, 10, "%10.6f", INDEX(a, k)); }
+	if (b) { snprintf(buffer + 35, 10, "%10.6f", INDEX(a, k)); }
+	if (c) { snprintf(buffer + 45, 10, "%10.6f", INDEX(a, k)); }
+	if (d) { snprintf(buffer + 55, 10, "%10.6f", INDEX(a, k)); }
+	for (j = 79; isspace(ch = buffer[j]) || ch == '\0'; j--) {}
+	buffer = Trim(buffer);
+	fprintf(efu, "%s\n", buffer);
+    }
+}
+
+/**
+ * Translate and scale the airfoil.  If no scaling or translation is
+ * done, just return.
+ */
+static void
+ScaleAirfoil(fastf_t scale, fastf_t xOrigin, fastf_t yOrigin,
+	     struct fortran_array *xupper, struct fortran_array *yupper, struct fortran_array *xlower, struct fortran_array *ylower)
+{
+    struct fortran_array *xu, *yu, *xl, *yl;
+    int i;
+    ALLOCATE(xu, SIZE(xupper));
+    ALLOCATE(yu, SIZE(yupper));
+    ALLOCATE(xl, SIZE(xlower));
+    ALLOCATE(yl, SIZE(ylower));
+
+    for (i = 1; i <= SIZE(xupper); i++) {
+	INDEX(xu, i) = xOrigin + scale * INDEX(xupper, i);
+    }
+    for (i = 1; i <= SIZE(yupper); i++) {
+	INDEX(yu, i) = yOrigin + scale * INDEX(yupper, i);
+    }
+    for (i = 1; i <= SIZE(xlower); i++) {
+	INDEX(xl, i) = xOrigin + scale * INDEX(xlower, i);
+    }
+    for (i = 1; i <= SIZE(ylower); i++) {
+	INDEX(yl, i) = yOrigin + scale * INDEX(ylower, i);
+    }
+
+    if (!ZERO(xOrigin) || !ZERO(yOrigin) || fabs(scale - 1.0) > 1e-6) {
+	PrintArrays(OUT, xu, yu, xl, yl, NULL, NULL);
+    }
+
+    PrintArrays(GNU, xu, yu, NULL, NULL, NULL, NULL); /* Plot upper surface */
+    fprintf(GNU, " \n"); /* Invisible move to start of lower surface */
+    PrintArrays(GNU, xl, yl, NULL, NULL, NULL, NULL); /* Plot lower surface */
+    fclose(GNU); /* Plot is complete */
+
+    return;
+}
+
+void Welcome()
+{
+    const char *AUTHOR = "Ralph L. Carmichael, Public Domain Aeronautical Software";
+    char *fileName = (char *)bu_malloc(132, "naca456");
+    const char *GREETING = "COORDINATES OF NACA AIRFOILS";
+
+    dateTimeStr = GetDateTimeStr();
+
+    printf("%s\n", GREETING);
+    printf("Program naca456, version %s\n", VERSION);
+    printf("%s\n", AUTHOR);
+    while (1) {
+	char *fileNameWithExtension;
+	int len;
+	printf("Enter the name of the input file: ");
+	fgets(fileName, 132, stdin);
+	fileName = Trim(fileName);
+	len = strlen(fileName);
+	if (len == 0) {
+	    /* User gives up */
+	    exit(1);
+	}
+	IN = fopen(fileName, "r");
+	if (IN) { break; }
+	/* 5 for the .ext and the terminating null. */
+	fileNameWithExtension = (char *)bu_malloc(len + 5, "naca456");
+	bu_strlcpy(fileNameWithExtension, fileName, len + 1);
+	bu_strlcat(fileNameWithExtension, ".nml", len + 5);
+	IN = fopen(fileName, "r");
+	if (IN) { break; }
+	fileNameWithExtension[len + 1] = '\0';
+	bu_strlcat(fileNameWithExtension, ".inp", len + 5);
+	IN = fopen(fileName, "r");
+	if (IN) { break; }
+	printf("Unable to open %s.  Try again.\n", fileName);
+    }
+    printf("Reading from %s\n", fileName);
+    DBG = fopen("naca.dbg", "w");
+    fprintf(DBG, "%s\n", GREETING);
+    fprintf(DBG, "Created by naca456, version %s on %s\n", VERSION, dateTimeStr);
+    fprintf(DBG, "%s\n", AUTHOR);
+
+    OUT = fopen("naca.out", "w");
+    fprintf(OUT, "%s\n", GREETING);
+    fprintf(OUT, "Created by naca456, version %s on %s\n", VERSION, dateTimeStr);
+    fprintf(OUT, "%s\n", AUTHOR);
+
+    GNU = fopen("naca.gnu", "w");
+    return;
+}
+
 /*
  * Local Variables:
  * tab-width: 8
