1 // =================================
  2 // Copyright (c) 2022 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Collections;
  8 using System.IO;
  9 using System.Os;
 10 
 11 void PrintHelp()
 12 {
 13     Console.WriteLine("Usage: tail [options] [FILE]...");
 14     Console.WriteLine("Print last 10 lines of each file to standard output.");
 15     Console.WriteLine("Options:");
 16     Console.WriteLine("--help | -h");
 17     Console.WriteLine("  Print help and exit.");
 18     Console.WriteLine("--lines=[+]NUM | -n=[+]NUM");
 19     Console.WriteLine("  Print last NUM lines instead of first 10;");
 20     Console.WriteLine("  with the leading '+' print lines starting with line number NUM.");
 21 }
 22 
 23 void PrintTail(const List<string>& filesint lineCountbool startLine)
 24 {
 25     for (const string& file : files)
 26     {
 27         StreamReader reader(SharedPtr<Stream>());
 28         if (!file.IsEmpty())
 29         {
 30             reader = File.OpenRead(file);
 31         }
 32         else
 33         {
 34             if (IsConsole(0))
 35             {
 36                 reader = StreamReader(SharedPtr<Stream>(new FileStream(0)));
 37             }
 38             else
 39             {
 40                 reader = StreamReader(SharedPtr<Stream>(new BufferedStream(SharedPtr<Stream>(new FileStream(0)))));
 41             }
 42         }
 43         List<string> lines;
 44         while (!reader.EndOfStream())
 45         {
 46             string line = reader.ReadLine();
 47             lines.Add(line);
 48         }
 49         int n = cast<int>(lines.Count());
 50         int start = Max(n - lineCount0);
 51         if (startLine)
 52         {
 53             start = lineCount - 1;
 54         }
 55         for (int i = start; i < n; ++i;)
 56         {
 57             Console.WriteLine(lines[i]);
 58         }
 59     }
 60 }
 61 
 62 int main(int argcconst char** argv)
 63 {
 64     try
 65     {
 66         int lineCount = 10;
 67         List<string> files;
 68         bool startLine = false;
 69         for (int i = 1; i < argc; ++i;)
 70         {
 71             string arg = argv[i];
 72             if (arg.StartsWith("--"))
 73             {
 74                 if (arg == "--help")
 75                 {
 76                     PrintHelp();
 77                     return 1;
 78                 }
 79                 else if (arg.Find('=') != -1)
 80                 {
 81                     List<string> components = arg.Split('=');
 82                     if (components.Count() == 2)
 83                     {
 84                         if (components[0] == "--lines")
 85                         {
 86                             if (components[1].StartsWith("+"))
 87                             {
 88                                 startLine = true;
 89                             }
 90                             lineCount = ParseInt(components[1]);
 91                         }
 92                         else
 93                         {
 94                             throw Exception("unknown option '" + arg + "'");
 95                         }
 96                     }
 97                     else
 98                     {
 99                         throw Exception("unknown option '" + arg + "'");
100                     }
101                 }
102                 else
103                 {
104                     throw Exception("unknown option '" + arg + "'");
105                 }
106             }
107             else if (arg.StartsWith("-"))
108             {
109                 if (arg.Find('=') != -1)
110                 {
111                     List<string> components = arg.Split('=');
112                     if (components.Count() == 2)
113                     {
114                         if (components[0] == "-n")
115                         {
116                             if (components[1].StartsWith("+"))
117                             {
118                                 startLine = true;
119                             }
120                             lineCount = ParseInt(components[1]);
121                         }
122                         else
123                         {
124                             throw Exception("unknown option '" + arg + "'");
125                         }
126                     }
127                     else
128                     {
129                         throw Exception("unknown option '" + arg + "'");
130                     }
131                 }
132                 else
133                 {
134                     string options = arg.Substring(1);
135                     for (char o : options)
136                     {
137                         string uo;
138                         bool unknown = false;
139                         switch (o)
140                         {
141                             case 'h':
142                             {
143                                 PrintHelp();
144                                 return 1;
145                             }
146                             default:
147                             {
148                                 uo.Append(o);
149                                 unknown = true;
150                                 break;
151                             }
152                         }
153                         if (unknown)
154                         {
155                             throw Exception("unknown option '-" + uo + "'");
156                         }
157                     }
158                 }
159             }
160             else
161             {
162                 files.Add(arg);
163             }
164         }
165         if (files.IsEmpty())
166         {
167             files.Add(string());
168         }
169         PrintTail(fileslineCountstartLine);
170     }
171     catch (const Exception& ex)
172     {
173         Console.Error() << ex.ToString() << endl();
174         return 1;
175     }
176     return 0;
177 }