File: fpdserver.lpr

package info (click to toggle)
lazarus 2.0.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 214,460 kB
  • sloc: pascal: 1,862,622; xml: 265,709; cpp: 56,595; sh: 3,008; java: 609; makefile: 535; perl: 297; sql: 222; ansic: 137
file content (221 lines) | stat: -rw-r--r-- 6,041 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
program fpdserver;

{ FPDebug server

  Copyright (C) 2015 Joost van der Sluis joost@cnoc.nl

  This source is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
  License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later
  version.

  This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  details.

  A copy of the GNU General Public License is available on the World Wide Web at
  <http://www.gnu.org/copyleft/gpl.html>. You can also obtain it by writing to the Free Software Foundation, Inc., 59
  Temple Place - Suite 330, Boston, MA 02111-1307, USA.
}

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  Classes,
  SysUtils,
  CustApp,
  debugthread,
  DebugThreadCommand,
  DebugInOutputProcessor,
  DebugTCPServer,
  DebugConsoleServer,
  debugscriptserver;

type

  { TFPDServerApplication }

  TFPDServerApplication = class(TCustomApplication)
  protected
    procedure DoRun; override;
  public
    constructor Create(TheOwner: TComponent); override;
    procedure WriteHelp; virtual;
  end;

{ TFPDServerApplication }

procedure TFPDServerApplication.DoRun;
var
  ErrorMsg: String;
  DebugThread: TFpDebugThread;
  TCPServerThread: TFpDebugTcpServer;
  ScriptServerThread: TFpDebugScriptServer;
  ConsoleServerThread: TFpDebugConsoleServer;
  Port: integer;
  SensePorts: integer;
  ACommand: TFpDebugThreadCommand;
  ScriptFile: string;
  CommandStr: string;
begin
  // quick check parameters
  ErrorMsg:=CheckOptions('hf:tdp:a::is:', ['help','filename:','tcp','daemon','port:','autoport::','interactive','script:'], True);

  if not HasOption('i','interactive') then
    begin
    writeln('FPDebug Server');
    writeln('Copyright (c) 2015 by Joost van der Sluis');
    end;

  if ErrorMsg<>'' then
    begin
    writeln(ErrorMsg);
    writeln('For more help, try: '+ExtractFileName(ExeName)+' -h');
    Terminate;
    Exit;
    end;

  if HasOption('h', 'help') then
    begin
    WriteHelp;
    Terminate;
    Exit;
    end;

  CommandStr := GetOptionValue('p','port');
  if CommandStr<>'' then
    begin
    if not TryStrToInt(CommandStr, Port) then
      begin
      writeln('Invalid port number '''+CommandStr+'''');
      Terminate;
      Exit;
      end;
    end
  else
    Port := 9159;

  if HasOption('a','autoport') then
    begin
    CommandStr := GetOptionValue('a','autoport');
    if CommandStr<>'' then
      begin
      if not TryStrToInt(CommandStr, SensePorts) then
        begin
        writeln('Autoport should be an integer number. Invalid autoport value '''+CommandStr+'''');
        Terminate;
        Exit;
        end;
      end
    else
      SensePorts:=5
    end
  else
    SensePorts:=1;

  DebugThread := TFpDebugThread.Instance;

  if not HasOption('d','daemon') then
    ConsoleServerThread := TFpDebugConsoleServer.Create(DebugThread)
  else
    ConsoleServerThread := nil;

  if HasOption('t','tcp') then
    TCPServerThread := TFpDebugTcpServer.Create(DebugThread, Port, SensePorts)
  else
    TCPServerThread := nil;

  if HasOption('i','interactive') then
    begin
    if assigned(TCPServerThread) then
      begin
      TCPServerThread.WaitForInitialization(Port);
      end
    else
      Port := -1;
    writeln(TJSonInOutputProcessor.InteractiveInitializationMessage(Port));
    FlushThread;
    end;

  ScriptFile := GetOptionValue('s','script');
  if ScriptFile<>'' then
    ScriptServerThread := TFpDebugScriptServer.create(DebugThread, ScriptFile)
  else
    ScriptServerThread := nil;

  CommandStr := GetOptionValue('f', 'filename');
  if CommandStr<>'' then
    begin
    ACommand := TFpDebugThreadSetFilenameCommand.create(-1, null, @DebugThread.SendLogMessage);
    TFpDebugThreadSetFilenameCommand(ACommand).Filename:=CommandStr;
    DebugThread.QueueCommand(ACommand);
    end;

  while not Terminated do
    begin
    try
      CheckSynchronize(100);
    except
      on e: exception do
        writeln(StdErr, 'Exception: '+e.Message);
    end;
    end;

  if assigned(ConsoleServerThread) then
    ConsoleServerThread.Terminate;
  if assigned(TCPServerThread) then
    TCPServerThread.StopListening;
  if assigned(ScriptServerThread) then
    ScriptServerThread.Terminate;

  if assigned(ConsoleServerThread) then
    ConsoleServerThread.WaitFor;
  if assigned(TCPServerThread) then
    TCPServerThread.WaitFor;
  if assigned(ScriptServerThread) then
    ScriptServerThread.WaitFor;

  if assigned(TCPServerThread) then
    TCPServerThread.Free;
  if assigned(ConsoleServerThread) then
    ConsoleServerThread.Free;
  if assigned(ScriptServerThread) then
    ScriptServerThread.Free;

  DebugThread.Terminate;
  DebugThread.WaitFor;
end;

constructor TFPDServerApplication.Create(TheOwner: TComponent);
begin
  inherited Create(TheOwner);
  StopOnException:=True;
end;

procedure TFPDServerApplication.WriteHelp;
begin
  writeln('fpdserver [options]');
  writeln(' List of options without argument:');
  writeln('  -h --help        Show this help message');
  writeln('  -t --tcp         Start listening to incoming tcp-connections');
  writeln('  -d --daemon      Do not use the console in- or output');
  writeln('  -i --interactive Run in interactive mode for automatic parsing');
  writeln(' List of options with argument:');
  writeln('  -f --filename    Set the filename of the executable to debug');
  writeln('  -p --port        Set the port (9159) to listen for incoming tcp-connections');
  writeln('  -a --autoport    Try to bind to n (5) sequential ports when a port is in use');
  writeln('  -s --script      Load script with debug-commands');
end;

var
  Application: TFPDServerApplication;
begin
  Application:=TFPDServerApplication.Create(nil);
  CustomApplication:=Application;
  Application.Title := 'FPD Server';
  Application.Run;
  Application.Free;
end.