L4Re/departure

Annotated test_files/programs/clip.c

560:d3c01405b62d
19 months ago Paul Boddie Introduced error handling when the desired lines cannot be located.
paul@525 1
/*
paul@525 2
 * Show lines from a file.
paul@525 3
 *
paul@525 4
 * Copyright (C) 2022, 2023 Paul Boddie <paul@boddie.org.uk>
paul@525 5
 *
paul@525 6
 * This program is free software; you can redistribute it and/or
paul@525 7
 * modify it under the terms of the GNU General Public License as
paul@525 8
 * published by the Free Software Foundation; either version 2 of
paul@525 9
 * the License, or (at your option) any later version.
paul@525 10
 *
paul@525 11
 * This program is distributed in the hope that it will be useful,
paul@525 12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
paul@525 13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
paul@525 14
 * GNU General Public License for more details.
paul@525 15
 *
paul@525 16
 * You should have received a copy of the GNU General Public License
paul@525 17
 * along with this program; if not, write to the Free Software
paul@525 18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
paul@525 19
 * Boston, MA  02110-1301, USA
paul@525 20
 */
paul@525 21
paul@525 22
#include <l4/sys/err.h>
paul@525 23
paul@525 24
#include <stdio.h>
paul@525 25
#include <stdlib.h>
paul@525 26
#include <string.h>
paul@525 27
paul@525 28
#include <fsclient/client.h>
paul@525 29
#include <systypes/env.h>
paul@525 30
#include <systypes/fcntl.h>
paul@525 31
paul@525 32
paul@525 33
paul@525 34
/* Read a line from the file. */
paul@525 35
paul@525 36
static int readline(file_t *file, int *lineno, char **start, char **end)
paul@525 37
{
paul@525 38
  static char buf[256];
paul@525 39
  static offset_t current = 0, limit = 0;
paul@525 40
  char *newline = NULL;
paul@525 41
paul@525 42
  do
paul@525 43
  {
paul@525 44
    /* Obtain file content. */
paul@525 45
paul@525 46
    if (!limit)
paul@525 47
    {
paul@525 48
      limit = client_read(file, buf, 256);
paul@525 49
paul@525 50
      if (!limit)
paul@525 51
      {
paul@525 52
        *start = NULL;
paul@525 53
        *end = NULL;
paul@525 54
        return 0;
paul@525 55
      }
paul@525 56
paul@525 57
      current = 0;
paul@525 58
paul@525 59
      /* Start of line at start of buffer. */
paul@525 60
paul@525 61
      if (newline != NULL)
paul@525 62
      {
paul@525 63
        current += 1;
paul@525 64
        *start = buf;
paul@525 65
        *end = (char *) memchr(buf + current, (int) '\n', limit - current);
paul@525 66
paul@525 67
        if (*end == NULL)
paul@525 68
          *end = buf + limit;
paul@525 69
paul@525 70
        return 1;
paul@525 71
      }
paul@525 72
    }
paul@525 73
paul@525 74
    /* Find newline. */
paul@525 75
paul@525 76
    newline = (char *) memchr(buf + current, (int) '\n', limit - current);
paul@525 77
paul@525 78
    if (newline != NULL)
paul@525 79
    {
paul@525 80
      (*lineno)++;
paul@525 81
      current = newline - (char *) buf + 1;
paul@525 82
paul@525 83
      /* Start of line before end of buffer. */
paul@525 84
paul@525 85
      if (current < limit)
paul@525 86
      {
paul@525 87
        *start = newline + 1;
paul@525 88
        *end = (char *) memchr(buf + current, (int) '\n', limit - current);
paul@525 89
paul@525 90
        if (*end == NULL)
paul@525 91
          *end = buf + limit;
paul@525 92
paul@525 93
        return 1;
paul@525 94
      }
paul@525 95
paul@525 96
      /* Otherwise, reset the buffer to read the start of line. */
paul@525 97
paul@525 98
      else
paul@525 99
        limit = 0;
paul@525 100
    }
paul@525 101
paul@525 102
    /* No newline: read more data. */
paul@525 103
paul@525 104
    else
paul@525 105
      limit = 0;
paul@525 106
  }
paul@525 107
  while (1);
paul@525 108
}
paul@525 109
paul@525 110
paul@525 111
paul@525 112
int main(int argc, char *argv[])
paul@525 113
{
paul@525 114
  file_t *file;
paul@525 115
  int i, startline, numlines;
paul@525 116
  char *start, *end;
paul@525 117
paul@525 118
  if (argc < 4)
paul@525 119
    return 1;
paul@525 120
paul@525 121
  file = client_open(argv[1], O_RDONLY);
paul@525 122
paul@525 123
  if (!client_opened(file))
paul@525 124
  {
paul@525 125
    if (file != NULL)
paul@525 126
      printf("Error: %s\n", l4sys_errtostr(file->error));
paul@525 127
    else
paul@525 128
      printf("Could not open file.\n");
paul@525 129
paul@525 130
    while (1);
paul@525 131
  }
paul@525 132
paul@525 133
  startline = atoi(argv[2]);
paul@525 134
  numlines = atoi(argv[3]);
paul@525 135
paul@525 136
  i = 1;
paul@525 137
  while (i < startline)
paul@560 138
  {
paul@525 139
    if (!readline(file, &i, &start, &end))
paul@560 140
    {
paul@560 141
      printf("EOF error at line %d.\n", i);
paul@560 142
      return 1;
paul@560 143
    }
paul@560 144
  }
paul@525 145
paul@525 146
  while (i < startline + numlines)
paul@525 147
  {
paul@525 148
    fwrite(start, sizeof(char), end - start, stdout);
paul@525 149
    if (!readline(file, &i, &start, &end))
paul@560 150
    {
paul@560 151
      printf("EOF error at line %d.\n", i);
paul@560 152
      return 1;
paul@560 153
    }
paul@525 154
  }
paul@525 155
paul@525 156
  fputs("\n\n", stdout);
paul@525 157
paul@525 158
  client_close(file);
paul@525 159
  client_notifier_close(client_notifier_task());
paul@525 160
paul@525 161
  return 0;
paul@525 162
}
paul@525 163
paul@525 164
/* vim: tabstop=2 expandtab shiftwidth=2
paul@525 165
*/