+same_t *
+expand_variables(token, free)
+same_t *token;
+int free;
+{
+ same_t *head = 0;
+
+ if (!free) {
+ token = same_copy(token); /* Get our private copy */
+ }
+
+ while (token) {
+ char *string = token->string->string;
+ same_t *tmp = same_unlink(token);
+
+ if ((string[0] == '$') && (string[1] == '{')) { /* Expand time */
+ int len = strlen(string);
+
+ string[len-1] = 0;
+ head = same_cat(head, expand_variables(
+ value_of(same_item(string_lookup(string+2))), 1));
+ string[len-1] = '}';
+ } else {
+ head = same_cat(head, token);
+ }
+ token = tmp;
+ }
+ return head;
+}
+
+
+same_t *
+ws_merge(list)
+same_t *list;
+{
+ same_t *newlist = 0, *item;
+ int what = 0;
+
+ while (list) {
+ switch (what) {
+ case 0:
+ if (isspace(list->string->string[0])) {
+ ;
+ } else {
+ item = same_item(list->string);
+ what = 1;
+ }
+ break;
+ case 1:
+ if (isspace(list->string->string[0])) {
+ newlist = same_cat(newlist, item);
+ item = 0;
+ what = 0;
+ } else {
+ item = same_merge(item, same_item(list->string));
+ what = 1;
+ }
+ break;
+ }
+ list = same_unlink(list);
+ }
+ return same_cat(newlist, item);
+}
+
+
+same_t *
+variable(var_name)
+same_t *var_name;
+{
+ int length = strlen(var_name->string->string);
+ same_t *resolved;
+ char *newname;
+
+ if ((newname = malloc(length+1+3)) == 0) {
+ fprintf("Out of space for a variable name.\n");
+ exit(1);
+ }
+ newname[0] = '$';
+ newname[1] = '{';
+ strcpy(newname+2, var_name->string->string);
+ strcat(newname, "}");
+ resolved = same_item(string_lookup(newname));
+ free(newname);
+
+ return resolved;
+}
+
+
+same_t *
+shell_variable(var_name)
+same_t *var_name;
+{
+ int length = strlen(var_name->string->string);
+ same_t *resolved;
+ char *newname;
+
+ if ((newname = malloc(length+1+2)) == 0) {
+ fprintf("Out of space for a variable name.\n");
+ exit(1);
+ }
+ newname[0] = '$';
+ newname[1] = '$';
+ strcpy(newname+2, var_name->string->string);
+ resolved = same_item(string_lookup(newname));
+ free(newname);
+
+ return resolved;
+}
+
+same_t *
+for_statement(special, variable, list)
+same_t
+ *special,
+ *variable,
+ *list;
+{
+ variable->shell_item = special;
+ variable->value_list = list;
+ return variable;
+}
+
+same_t *
+do_command(forlist, commands)
+same_t
+ *forlist,
+ *commands;
+{
+ same_t
+ *special,
+ *command_list = 0,
+ *new_commands,
+ *tmp,
+ *shell_item,
+ *value_list = forlist->value_list;
+ char
+ *tmpstr,
+ *variable_name = forlist->string->string;
+
+ special = forlist->shell_item;
+ if (same_unlink(forlist->shell_item) != 0) {
+ yyerror("Unexpected second item in special part of do_command");
+ exit(1);
+ }
+
+ while ((shell_item = value_list) != 0) {
+ value_list = same_unlink(shell_item);
+ /* Visit each item in commands. For each shell variable which
+ * matches ours, replace it with ours.
+ */
+ new_commands = same_copy(commands);
+ for (visit(new_commands, tmp); !visited(tmp); visit_next(tmp)) {
+ tmpstr = tmp->string->string;
+ if ((tmpstr[0] == '$') && (tmpstr[1] == '$')) {
+ if (strcmp(tmpstr+2, variable_name) == 0) {
+ same_replace(tmp, same_copy(shell_item));
+ }
+ }
+ }
+ visit_end();
+ command_list = same_cat(command_list, new_commands);
+ }
+ return same_cat(command_list, same_copy(newline));
+}
+
+