From: andre@ph.tn.tudelft.nl (Andre Verweij)
Subject: Galaxy Tool
Summary: Program to make input into galaxy easier.
Keywords: galaxy fleets variables
Organization: Delft University of Technology
Date: Thu, 19 Nov 1992 21:10:34 GMT

Some time ago someone asked if it was possible to join groups into
a fleet. As this is still not possible in Russell's game, we all have
to type a command for every group seperately. This brought me on the
idea to use variables. The program I include below can handle 
variables. A variable is defined as follows :

varname = {one,two,three,four}

The varname and the arguments can contain arbitrary characters,
except spaces, commas, tabs and braces or equal signs.
A variable is used by putting a $ in front of its name.

In the above example:
S 105 $varname 1
would be expanded into :
S 105 one 1
S 105 two 1
S 105 three 1
S 105 four 1

Also multiple substitutions can be done on a single line.
Look in the code for the maximum number of arguments in a variable.

I am open for suggestions to improve this peace of software.

Andre Verweij
andre@duteinh.et.tudelft.nl
Delft University of Technology.

================================================================================
Author:
Andre Verweij
andre@duteinh.et.tudelft.nl
Delft University of Technology.

#include <stdio.h>

typedef struct variable {
    char      name[15];
    int       nentries;
    char      entries[20][15];
    struct variable *next;
}         VARIABLE;

VARIABLE *varlist;

int       readline (file, buffer)
    FILE     *file;
    char     *buffer;
{
    int       length;
    char      ch;

    length = 0;
    while (((ch = getc (file)) != EOF) && (ch != '\n'))
	buffer[length++] = ch;
    if (ch == EOF)
	return (EOF);
    else {
	buffer[length] = '\0';
	return (length);
    }
}

evaluate (buffer, file)
    char     *buffer;
    FILE     *file;
{
    int       wlen;
    int       nentries;
    char     *ch;
    char      scanned[200];
    char      newline[200];
    char      word[20];
    VARIABLE *var;

    ch = buffer;
    wlen = 0;
    scanned[0] = '\0';
    do {
	switch (*ch) {
	case '=':	     /* variable declaration */
	    if (varlist == NULL) {
		var = varlist = (VARIABLE *) malloc (sizeof (VARIABLE));
		var->next = NULL;
	    } else {
		var = varlist;
		while ((var->next != NULL) && (strcmp (var->name, word) != 0))
		    var = var->next;
		if (strcmp (var->name, word) != 0) {	/* create a new var */
		    var->next = (VARIABLE *) malloc (sizeof (VARIABLE));
		    var = var->next;
		    var->next = NULL;
		}
	    }
	    strcpy (var->name, word);
	    nentries = 0;
	    wlen = 0;
	    while (*ch++ != '{');
	    while (*ch != '}') {
		if (*ch == ',') {
		    word[wlen] = '\0';
		    strcpy (var->entries[nentries++], word);
		    wlen = 0;
		} else if (*ch != ' ')
		    word[wlen++] = *ch;
		ch++;
	    }
	    word[wlen] = '\0';
	    strcpy (var->entries[nentries++], word);
	    var->nentries = nentries;
	    return (0);
	case '$':	     /* variable substitution */
	    ch++;
	    wlen = 0;
	    while ((*ch != ' ') && (*ch != '\0') && (*ch != '\t'))
		word[wlen++] = *ch++;
	    word[wlen] = '\0';
	    var = varlist;
	    while ((var != NULL)
		   && (strcmp (word, var->name) != 0))
		var = var->next;
	    if (var == NULL) {
		printf ("Unkown variable\n");
		exit (1);
	    }
	    for (nentries = 0; nentries < var->nentries; nentries++) {
		sprintf (newline, "%s%s%s",
			 scanned, var->entries[nentries], ch);
		evaluate (newline, file);
	    }
	    return (0);
	case ' ':	     /* white space */
	case '\t':
	    word[wlen] = '\0';
	    strcat (scanned, word);
	    strcat (scanned, " ");
	    wlen = 0;
	    break;
	case '\0':	     /* end of line */
	    word[wlen] = '\0';
	    strcat (scanned, word);
	    fprintf (file, "%s\n", scanned);
	    return (1);
	default:
	    word[wlen++] = *ch;
	    break;
	}
    } while (*ch++ != '\0');
}

main (argc, argv)
    int       argc;
    char     *argv[];
{
    FILE     *input,
             *output;
    char      line[200];

    switch (argc) {
    case 1:
	input = stdin;
	output = stdout;
	break;
    case 2:
	input = fopen (argv[1], "r");
	output = stdout;
	break;
    case 3:
	input = fopen (argv[1], "r");
	output = fopen (argv[2], "w");
	break;
    default:
	printf ("Invalid number of parameters\n");
	exit (1);
    }
    if ((input == NULL) || (output == NULL)) {
	printf ("Error in opening input/output files\n");
	exit (1);
    }
    while (readline (input, line) != EOF)
	evaluate (line, output);

    if (input != stdin)
	fclose (input);
    if (output != stdout)
	fclose (output);
}