implementation class
ReadOnlyFile: State, Conditions, Constants
{
  <doc> The condition used by the ReadOnlyFile to signal opening problems.
      </doc>
  static ConditionClass file-open-problem;
}

<doc> Set up the condition classes.  </doc>
void
  load Array arguments
{
  file-open-problem = [ConditionClass with file-error name "file-open-problem"];
}

<doc> Open the indicated file.  </doc>
ReadOnlyFile (the_file)
  open String filename
{
  the_file = [[self alloc] initWithFilename filename];
  if (![the_file open])
    return nil;
}

<doc> The main method.  </doc>
int
  main Array arguments
{
  /* Setup a handler for FILE-OPEN-PROBLEM conditions.  */
  bind ((file-open-problem,
         {
           /* Retrieve the file object to which the condition applies.  */
           ReadOnlyFile file = [condition object];

           /* Describe the problem to the user and prompt for input.  */
           [[[stdio err] print ("trouble opening: ", [file name])] nl];
           [[[stdio err] print ("reason: ", [condition message])] nl];
           [[[stdio err] print "alternative (RET for original)? "] nl];

           /* Read a line of input.  */
           String input = [[stdio err] readLine];

           /* If the input is an empty line, return NIL, indicating that
              we did handle this condition, but that an alternative
              filename was not entered.  Otherwise, return the filename
              entered by the user.  As long as we do not return the
              CONDITION object, we will have handled this condition.  */
           [input length] > 0 ? input : nil;
         }))
    ({
      [[[stdio err] print [self open arguments[0]]] nl];
    });
}

end;

implementation instance
ReadOnlyFile
{
  <doc> Our name.  </doc>
  public String name;

  <doc> The file we employ to do the real thing.  </doc>
  File file;
}

<doc> Designated initializer.  </doc>
id
  initWithFilename String filename
{
  name = filename;

  /* Pass to super's designated initializer.  */
  = [super init];
}

<doc> Try to open the file, returning {TRUE} only upon success.  </doc>
boolean (success)
  open
{
  for (;;)
    {
      /* Try to open, and return TRUE upon success.  */
      file = [File open name input: YES flags: FILE_NOT_EXIST_NOTHING];
      if (file != nil)
        return TRUE;

      /* See if we can get an alternative filename.  */
      String alternative_name = [Runtime perror nil for self
					 class file-open-problem raise NO];
      if (!alternative_name)
        {
          /* The condition was not handled.  */
          return FALSE;
        }

      /* Make the ALTERNATIVE_NAME our new name.  */
      name = alternative_name;
    }
}

<doc> Also write the {name}.  </doc>
OutputStream
  writeFields OutputStream s
{
  = [[super writeFields s] print (" name=", name)];
}

end;
