OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [tools/] [src/] [tools/] [ecostest/] [common/] [eCosTest.cpp] - Blame information for rev 438

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 26 unneback
//####COPYRIGHTBEGIN####
2
//                                                                          
3
// ----------------------------------------------------------------------------
4
// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5
//
6
// This program is part of the eCos host tools.
7
//
8
// This program is free software; you can redistribute it and/or modify it 
9
// under the terms of the GNU General Public License as published by the Free 
10
// Software Foundation; either version 2 of the License, or (at your option) 
11
// any later version.
12
// 
13
// This program is distributed in the hope that it will be useful, but WITHOUT 
14
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
15
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
16
// more details.
17
// 
18
// You should have received a copy of the GNU General Public License along with
19
// this program; if not, write to the Free Software Foundation, Inc., 
20
// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21
//
22
// ----------------------------------------------------------------------------
23
//                                                                          
24
//####COPYRIGHTEND####
25
//=================================================================
26
//
27
//        eCosTest.cpp
28
//
29
//        Test class
30
//
31
//=================================================================
32
//=================================================================
33
//#####DESCRIPTIONBEGIN####
34
//
35
// Author(s):     sdf
36
// Contributors:  sdf
37
// Date:          1999-04-01
38
// Description:   This class abstracts a test for use in the testing infrastructure
39
// Usage:
40
//
41
//####DESCRIPTIONEND####
42
///////////////////////////////////////////////////////////////////////////////
43
#include "eCosStd.h"
44
#include "eCosTest.h"
45
#include "eCosTestPlatform.h"
46
#include "eCosTrace.h"
47
#include "TestResource.h"
48
#include "eCosTestUtils.h"
49
#include "eCosSocket.h"
50
#include "eCosSerial.h"
51
#include "eCosTestSerialFilter.h"
52
#include "eCosTestDownloadFilter.h"
53
#include "Properties.h"
54
#include "Subprocess.h"
55
 
56
#define WF(n) (n+50)/1000,((n+50)%1000)/100     // Present n as whole and fractional part.  Round to nearest least significant digit
57
#define WFS   _T("%u.%u")                           // The format string to output the above
58
 
59
LPCTSTR  const CeCosTest::arResultImage[1+CeCosTest::StatusTypeMax]=
60
{_T("NotStarted"), _T("NoResult"), _T("Inapplicable"), _T("Pass"), _T("DTimeout"), _T("Timeout"), _T("Cancelled"), _T("Fail"), _T("AssertFail"), _T("Unknown")};
61
 
62
CeCosTest *CeCosTest::pFirstInstance=0;
63
int CeCosTest::InstanceCount=0;
64
 
65
LPCTSTR  const CeCosTest::arServerStatusImage[1+CeCosTest::ServerStatusMax]={
66
  _T("Busy"), _T("Ready"), _T("Can't run"), _T("Connection failed"), _T("Locked"), _T("Bad server status")};
67
LPCTSTR  CeCosTest::ExecutionParameters::arRequestImage [1+ExecutionParameters::RequestTypeMax]={
68
  _T("Run"), _T("Query"), _T("Lock"), _T("Unlock"), _T("Stop"), _T("Bad request") };
69
 
70
static bool CALLBACK IsCancelled(void *pThis)
71
{
72
  return CeCosTest::Cancelled==((CeCosTest *)pThis)->Status();
73
}
74
 
75
// Ctors and dtors:
76
CeCosTest::CeCosTest(const ExecutionParameters &e, LPCTSTR pszExecutable,LPCTSTR pszTitle):
77
  m_pspPipe(0),
78
  m_nStrippedSize(0),
79
  m_nFileSize(0),
80
  m_bDownloading(false),
81
  m_pSock(0),
82
  m_ep(e),
83
  m_strTitle(pszTitle),
84
  m_Status(NotStarted),
85
  m_nDownloadTime(0),
86
  m_nTotalTime(0),
87
  m_nMaxInactiveTime(0),
88
  m_pResource(0),
89
  m_psp(0)
90
{
91
 
92
  assert(e.Platform());
93
 
94
  SetExecutable (pszExecutable);
95
 
96
  TRACE(_T("%%%% Create test instance %08x count:=%d\n"),this,InstanceCount+1);
97
 
98
  // By recording the path now, we ensure processes are always run in the context in which the test instance
99
  // is created (important for the ConfigTool to be able to call PrepareEnvironment).
100
 
101
#ifdef _WIN32
102
  // for some reason _tgetenv() doesn't return the PATH set
103
  // by PrepareEnvironment() so use GetEnvironmentVariable() instead
104
  // JLD - 2000-06-09
105
  String strPath;
106
  int nSize=GetEnvironmentVariable(_T("PATH"), NULL, 0);
107
  GetEnvironmentVariable(_T("PATH"), strPath.GetBuffer(nSize), nSize);
108
  strPath.ReleaseBuffer();
109
  m_strPath=strPath;
110
#else
111
  LPCTSTR pszPath=_tgetenv(_T("PATH"));
112
  if(pszPath){
113
    m_strPath=pszPath;
114
  }
115
#endif
116
 
117
  ENTERCRITICAL;
118
  InstanceCount++;
119
  m_pNextInstance=pFirstInstance;
120
  if(m_pNextInstance){
121
    m_pNextInstance->m_pPrevInstance=this;
122
  }
123
  m_pPrevInstance=0;
124
  pFirstInstance=this;
125
  LEAVECRITICAL;
126
 
127
}
128
 
129
CeCosTest::~CeCosTest()
130
{
131
  for(int i=0;i<(signed)m_arpExecsp.size();i++){
132
    delete (CSubprocess *)m_arpExecsp[i];
133
  }
134
  delete m_pspPipe;
135
 
136
  TRACE(_T("%%%% Delete test instance %08x\n"),this);
137
  Cancel();
138
  CloseSocket();
139
  if(m_pResource){
140
    m_pResource->Release();
141
    //delete m_pResource;
142
    //m_pResource=0;
143
  }
144
 
145
  VTRACE(_T("~CeCosTest(): EnterCritical and decrease instance count\n"));
146
  ENTERCRITICAL;
147
  InstanceCount--;
148
  TRACE(_T("%%%% Destroy instance.  Instance count:=%d\n"),InstanceCount);
149
  if(pFirstInstance==this){
150
    pFirstInstance=m_pNextInstance;
151
  }
152
  if(m_pPrevInstance){
153
    m_pPrevInstance->m_pNextInstance=m_pNextInstance;
154
  }
155
  if(m_pNextInstance){
156
    m_pNextInstance->m_pPrevInstance=m_pPrevInstance;
157
  }
158
  LEAVECRITICAL;
159
}
160
 
161
bool CeCosTest::RunRemote (LPCTSTR pszRemoteHostPort)
162
{
163
  bool rc=false;
164
  TRACE(_T("RunRemote\n"));
165
  m_strExecutionHostPort=pszRemoteHostPort;
166
  m_Status=NotStarted;
167
 
168
  VTRACE(_T("RemoteThreadFunc()\n"));
169
 
170
  // Find a server.
171
  ConnectForExecution();
172
  if(Cancelled!=Status()){
173
    if(m_ep.Platform()->ServerSideGdb()){
174
      // The executable is transmitted to the server for execution.
175
      // Send file size
176
      if(m_pSock->sendInteger(m_nFileSize,_T("file size"))&&m_nFileSize>0){
177
        int nBufSize=MIN(10000,m_nFileSize);
178
        Buffer b(nBufSize);
179
        TRACE(_T("Sending [%d bytes]\n"), m_nFileSize);
180
        int nToSend=m_nFileSize;
181
        FILE *f1=_tfopen(m_strExecutable,_T("rb"));
182
        if(0==f1){
183
          Log(_T("Failed to open %s - %s\n"),(LPCTSTR)m_strExecutable,strerror(errno));
184
        } else {
185
          while (nToSend>0){
186
            int nRead=fread( b.Data(), 1, nBufSize, f1);
187
            if(nRead<=0){
188
              Log(_T("Failure reading %s - %s\n"),(LPCTSTR)m_strExecutable,strerror(errno));
189
              break;
190
            }
191
            if(!send( b.Data(), nRead, _T("executable"))){
192
              Log(_T("Failure sending %s - %s\n"),(LPCTSTR)m_strExecutable,(LPCTSTR)m_pSock->SocketErrString());
193
              break;
194
            }
195
            nToSend-=nRead;
196
          }
197
          fclose(f1);
198
          f1=0;
199
          if(nToSend>0){
200
            TRACE(_T("done [%d bytes sent]\n"),m_nFileSize-nToSend);
201
            Log(_T("Failed to transmit %s - %d/%d bytes sent\n"),(LPCTSTR)m_strExecutable,m_nFileSize-nToSend,m_nFileSize);
202
          } else {
203
            TRACE(_T("done\n"));
204
            rc=true;
205
          }
206
        }
207
        if(!recvResult(9*1000*60)){ // nine minutes
208
          Log(_T("Failed to receive result from remote server\n"));
209
          rc=false;
210
        }
211
        m_pSock->sendInteger(456); // send an ack [n'importe quoi]
212
        CloseSocket();
213
      }
214
    } else {
215
      // The server sets up a connection between port and tcp/ip socket, and gdb is run locally
216
      // Big timeout here because we have to wait for the target to be reset
217
      // We do this:
218
      // do {
219
      //     target ready indicator (0==fail, 1==ready, 2==fail and will retry)
220
      //     any output so far
221
      // } while (2==target ready indicator)
222
      // read host:port
223
      String strHostPort;
224
      if(GetTargetReady(strHostPort)){
225
        // Fix up a resource to represent permission to use the host:port we have been told about
226
        CTestResource resource;
227
        resource.SetTarget(m_ep.PlatformName());
228
        resource.SetDownload(strHostPort,0);
229
        m_pResource=&resource;
230
        RunLocal();
231
        m_pResource=0;
232
        m_pSock->sendInteger(Status(),_T("Terminating ack"));
233
        m_pSock->Close();
234
        rc=true;
235
      }
236
    }
237
  }
238
  TRACE(_T("RemoteThreadFunc - exiting\n"));
239
  return rc;
240
}
241
 
242
// Run the test locally
243
bool CeCosTest::RunLocal()
244
{
245
  bool rc=false;
246
 
247
  TRACE(_T("RunLocal %s\n"),(LPCTSTR)Executable());
248
 
249
  if(!CeCosTestUtils::IsFile(Executable())){
250
    Log(_T("Cannot run - %s is not a file\n"),(LPCTSTR)Executable());
251
  } else if(0==m_pResource && 0==CTestResource::Count(m_ep)){
252
    Log(_T("Cannot run a %s test\n"),(LPCTSTR)m_ep.PlatformName());
253
  } else {
254
 
255
    m_Status=NotStarted;
256
 
257
    TRACE(_T("LocalThreadFunc - target=%s\n"),(LPCTSTR)m_ep.PlatformName());
258
    // Acquire a port (our caller may have done this for us)
259
    VTRACE(_T("LocalThreadFunc():Trying to acquire a port\n"));
260
    if(0==m_pResource){
261
      for(;;){
262
        m_pResource=CTestResource::GetResource(m_ep);
263
        if(m_pResource||Cancelled==Status()){
264
          break;
265
        }
266
        CeCosThreadUtils::Sleep(2000);
267
        TRACE(_T("Waiting for a port\n"));
268
      }
269
    }
270
    VTRACE(_T("\nPort acquired!\n"));
271
 
272
    if(Cancelled!=Status()){
273
      // This means we have acquired a local port 
274
      bool bTargetReady=false;
275
      if(!m_pResource->HasReset()){
276
        bTargetReady=true;
277
      } else {
278
        bTargetReady=(CResetAttributes::RESET_OK==m_pResource->Reset(0,this));
279
      }
280
      // we may proceed to execute the test
281
      if(bTargetReady){
282
        SetStatus(NotStarted);
283
 
284
        if(NOTIMEOUT==m_ep.DownloadTimeout()){
285
          // No elapsed timeout given - calculate from knowledge of executable size and baud rate
286
          // 10 baud ~= 1 byte/sec, but we halve this to account for download in hex :-(
287
          // We use a minimum of 30 seconds and double the calculated result for safety
288
          // Note that the baud rate is generally unknown on the client side.
289
          int nBaud=m_pResource->Baud();
290
          if(0==nBaud){
291
            CTestResource *pExecutionResource=CTestResource::Lookup(m_strExecutionHostPort);
292
            if(pExecutionResource){
293
              nBaud=pExecutionResource->Baud();
294
            }
295
          }
296
          if(0==nBaud){
297
            nBaud=38400;
298
          }
299
 
300
          int nBytesPerSec=(nBaud/10)/2; // division by 2 assumes download in "ascii" (2 bytes/char)
301
          m_ep.SetDownloadTimeout (1000*MAX(30,2*(m_nStrippedSize/nBytesPerSec)));
302
          TRACE(_T("Estimated download time %d sec (%d bytes @ %d bytes/sec [%d baud])\n"),m_nStrippedSize/nBytesPerSec,m_nStrippedSize,nBytesPerSec,nBaud);
303
        }
304
 
305
        TRACE(_T("Active timeout=%d download timeout=%d\n"),m_ep.ActiveTimeout(), m_ep.DownloadTimeout());
306
 
307
        GetInferiorCommands(m_arstrInferiorCmds);
308
        String strInferior(m_ep.Platform()->Inferior());
309
        strInferior.Replace(_T("%e"),CygPath(m_strExecutable),true);
310
        RunInferior(strInferior);
311
        rc=true;
312
      }
313
    }
314
    if(m_pResource){
315
      m_pResource->Release();
316
      m_pResource=0;
317
    }
318
    TRACE(_T("RunLocal - exiting\n"));
319
  }
320
 
321
  return rc;
322
}
323
 
324
void CeCosTest::Cancel ()
325
{
326
  SetStatus(Cancelled);
327
}
328
 
329
CeCosTest::ServerStatus CeCosTest::Connect (LPCTSTR pszHostPort, CeCosSocket *&pSock, const ExecutionParameters &e,String &strInfo,Duration dTimeout)
330
{
331
  // Find out whether this host is receptive
332
  ServerStatus s=CONNECTION_FAILED;
333
  pSock=new CeCosSocket(pszHostPort,dTimeout);
334
  int nStatus;
335
  if(pSock->Ok() &&
336
    pSock->sendString(e.Image(), _T("execution parameters")) &&
337
    pSock->recvInteger(nStatus,_T("ready status")) &&
338
    pSock->recvString(strInfo)){
339
    s=(ServerStatus)MIN(nStatus,ServerStatusMax);
340
  }
341
  if(SERVER_READY!=s || ExecutionParameters::RUN!=e.Request()){
342
    delete pSock;
343
    pSock=0;
344
  }
345
  return s;
346
}
347
 
348
// Initiate a connection to hostName:nPort and acquire the ready status [retry until this is achieved]
349
// The socket (m_pSock) is left open.
350
// This function is either called with m_strExecutionHostPort already set to a desired server
351
// or else m_strExecutionHostPort empty (in which case the server is / dynamically)
352
 
353
void CeCosTest::ConnectForExecution ()
354
{
355
  bool bSchedule=(0==m_strExecutionHostPort.size());
356
  Duration nDelay=2000;
357
 
358
  m_pSock=0;
359
 
360
  bool *arbHostTried=0;
361
 
362
  while(Cancelled!=Status()){
363
    StringArray arstrHostPort,arstrTries;
364
    int nChoices;
365
 
366
    if(bSchedule){
367
      if(!CTestResource::GetMatches(m_ep,arstrHostPort)){
368
        Log(_T("Could not establish matches\n"));
369
        continue;
370
      }
371
      nChoices=arstrHostPort.size();
372
      if(nChoices>0){
373
        TRACE(_T("ConnectForExecution: choices are:\n"));
374
        for(int i=0;i<nChoices;i++){
375
          TRACE(_T("\t%s\n"),(LPCTSTR)arstrHostPort[i]);
376
        }
377
      }
378
    } else {
379
      // Server has already been picked by caller
380
      nChoices=1;
381
      String str;
382
      arstrHostPort.push_back(m_strExecutionHostPort);
383
    }
384
 
385
    if(nChoices>0){
386
      delete [] arbHostTried;
387
      arbHostTried=new bool[nChoices];
388
      for(int i=0;i<nChoices;i++){
389
        arbHostTried[i]=false;
390
      }
391
 
392
      // Loop around the choices
393
      for(int nUntried=nChoices;nUntried>0;nUntried--) {
394
        // Select one we haven't tried already:
395
        int nChoice;
396
        do {
397
          nChoice=rand() % nChoices;
398
        } while (arbHostTried[nChoice]);
399
 
400
        m_strExecutionHostPort=arstrHostPort[nChoice];
401
 
402
        TRACE(_T("ConnectForExecution: chosen %s\n"),(LPCTSTR)m_strExecutionHostPort);
403
        if(CeCosSocket::IsLegalHostPort(m_strExecutionHostPort)){
404
          // If we're using the resource server we had better check that the host
405
          // we are about to lock has not been resource-locked (the other match checks
406
          // will of course always succeed)
407
          String strInfo;
408
          ServerStatus s=bSchedule && !CTestResource::Matches(m_strExecutionHostPort,m_ep)?SERVER_LOCKED:
409
            Connect(m_strExecutionHostPort,m_pSock,m_ep,strInfo);
410
          arbHostTried[nChoice]=true;
411
          TRACE(_T("Connect: %s says %s %s\n"),(LPCTSTR)m_strExecutionHostPort,(LPCTSTR)Image(s),(LPCTSTR)strInfo);
412
          CTestResource *pResource=CTestResource::Lookup(m_strExecutionHostPort);
413
          if(pResource){
414
            String str;
415
            str.Format(_T("%s %s %s"),(LPCTSTR)pResource->Image(),(LPCTSTR)strInfo,(LPCTSTR)Image(s));
416
            arstrTries.push_back(str);
417
          }
418
          if(SERVER_READY==s){
419
            // So that's ok then.  We're outta here.
420
            INTERACTIVE(_T("Connected to %s\n"),(LPCTSTR)m_strExecutionHostPort);
421
            goto Done;
422
          } else {
423
            delete m_pSock;
424
            m_pSock=0;
425
          }
426
        }
427
      }
428
    }
429
 
430
    INTERACTIVE(_T("Warning - could not connect to any test servers:\n"));
431
    if(arstrTries.size()>0){
432
      for(unsigned int i=0;i<arstrTries.size();i++){
433
        INTERACTIVE(_T("    %s\n"),(LPCTSTR)arstrTries[i]);
434
      }
435
    } else {
436
      INTERACTIVE(_T("No servers available to execute %s test:\n"),(LPCTSTR)m_ep.PlatformName());
437
      ENTERCRITICAL;
438
      for(CTestResource *pResource=CTestResource::First();pResource;pResource=pResource->Next()){
439
        INTERACTIVE(_T("    %s\n"),(LPCTSTR)pResource->Image());
440
      }
441
      LEAVECRITICAL;
442
    }
443
    INTERACTIVE(_T("Retry in %d seconds...\n"),nDelay/1000);
444
 
445
    // We have tried all possibilities - sleep before retrying
446
    CeCosThreadUtils::Sleep(nDelay);
447
 
448
    if(Cancelled==m_Status){
449
      TRACE(_T("ConnectForExecution : cancelled\n"));
450
      goto Done;
451
    }
452
    if(nDelay<20*1000){
453
      nDelay+=rand() % 500;
454
    }
455
  }
456
Done:
457
  delete [] arbHostTried;
458
}
459
 
460
void CeCosTest::SetStatus (StatusType status)
461
{
462
  ENTERCRITICAL;
463
  if((int)status>(int)m_Status){
464
    TRACE(_T("Status <- %s\n"),(LPCTSTR)Image(status));
465
    m_Status=status;
466
  }
467
  LEAVECRITICAL;
468
}
469
 
470
bool CeCosTest::WaitForAllInstances(int nPoll,Duration nTimeout)
471
{
472
  Time t0=Now();
473
  while(InstanceCount>0){
474
    CeCosThreadUtils::Sleep(nPoll);
475
    if(NOTIMEOUT!=nTimeout && Now()-t0>nTimeout){
476
      return false;
477
    }
478
  }
479
  return true;
480
}
481
 
482
void CeCosTest::DeleteAllInstances()
483
{
484
  while(pFirstInstance){
485
    delete pFirstInstance;
486
  }
487
}
488
 
489
void CeCosTest::CancelAllInstances()
490
{
491
  ENTERCRITICAL;
492
  for(CeCosTest *pTest=pFirstInstance;pTest;pTest=pTest->m_pNextInstance){
493
    pTest->Cancel();
494
  }
495
  LEAVECRITICAL;
496
}
497
 
498
// The same format is used for _stscanf as for Format (which is like printf), so restrict to the format specifiers
499
// the former is happy with.  In particular, do not use %-3s etc...
500
 
501
LPCTSTR CeCosTest::pszFormat=
502
// 1999-01-15 17:24:36 Fireblade:5002 MN10300 sin.exe 219k/134k Pass sin download=106.3/117.0 Total=107.6 Max inactive=1.0/300.0    
503
_T("%04d-%02d-%02d %02d:%02d:%02d ")                   // Time
504
_T("%15s ")                                            // Execution host:port
505
_T("%16s ")                                             // Target
506
_T("%30s ")                                            // Executable tail
507
_T("%11s ")                                            // Result
508
_T("%dk/%dk ")                                         // Sizes
509
_T("D=") WFS _T("/") WFS _T(" Total=") WFS _T(" ")     // Times
510
_T("E=") WFS _T("/") WFS _T(" ")
511
_T("\"%s\"");
512
 
513
bool CeCosTest::Value (
514
  LPCTSTR pszStr,
515
  struct tm &t,
516
  StatusType &status,
517
  String &target,
518
  String &strExecutionHostPort,
519
  String &strExecutableTail,
520
  String &strTitle,
521
 
522
  int &nFileSize,
523
  Duration &nTotalTime,
524
  Duration &nMaxInactiveTime,
525
  Duration &nDownloadTime,
526
  Duration &nDownloadTimeout,
527
  Duration &nActiveTimeout,
528
 
529
  int &nDownloadedSize)
530
{
531
  int nLen=_tcslen(pszStr);
532
  String strStatus;
533
 
534
  nFileSize=nTotalTime=nMaxInactiveTime=nDownloadTime=nDownloadTimeout=nActiveTimeout=nDownloadedSize=0;
535
 
536
  int nTotalTimeFrac=0;
537
  int nMaxInactiveTimeFrac=0;
538
  int nActiveTimeoutFrac=0;
539
  int nDownloadTimeFrac=0;
540
  int nDownloadTimeoutFrac=0;
541
 
542
  static String strFormat;
543
  if(0==strFormat.size()){
544
    // Construct a version of the format string sans length attributes for %s items
545
    LPCTSTR c=pszFormat;
546
    TCHAR *d=strFormat.GetBuffer(_tcslen(pszFormat));
547
    while(_TCHAR('\0')!=*c){
548
      if(_TCHAR('%')==c[0] && _istdigit(c[1])){
549
        *d++=_TCHAR('%');
550
        do {
551
          c++;
552
        } while (_istdigit(*c));
553
      }
554
      *d++=*c++;
555
    }
556
    *d=_TCHAR('\0');
557
    strFormat.ReleaseBuffer();
558
  }
559
 
560
  _stscanf(pszStr,
561
    strFormat,
562
    &t.tm_year,&t.tm_mon,&t.tm_mday,
563
    &t.tm_hour,&t.tm_min,&t.tm_sec,         // Time of day
564
    strExecutionHostPort.GetBuffer(1+nLen),       // Execution host:port
565
    target.GetBuffer(1+nLen),                  // Target
566
    strExecutableTail.GetBuffer(1+nLen),          // Executable
567
    strStatus.GetBuffer(1+nLen),                  // Result
568
    &nDownloadedSize,&nFileSize,            // Sizes
569
    &nDownloadTime,&nDownloadTimeFrac,      // Times
570
    &nDownloadTimeout,&nDownloadTimeoutFrac,
571
    &nTotalTime,&nTotalTimeFrac,
572
    &nMaxInactiveTime,&nMaxInactiveTimeFrac,
573
    &nActiveTimeout,&nActiveTimeoutFrac,
574
    strTitle.GetBuffer(1+nLen)                    // Title
575
    );
576
 
577
  strExecutionHostPort.ReleaseBuffer();
578
  target.ReleaseBuffer();
579
  strExecutableTail.ReleaseBuffer();
580
  strStatus.ReleaseBuffer();
581
  strTitle.ReleaseBuffer();
582
  status=StatusTypeValue(strStatus);
583
 
584
  LPCTSTR c1=_tcschr(pszStr,_TCHAR('"'));
585
  if(c1){
586
    c1++;
587
    LPCTSTR c2=_tcschr(c1+1,_TCHAR('"'));
588
    if(c2){
589
      strTitle=String(c1,c2-c1);
590
    }
591
  }
592
 
593
  nTotalTime=nTotalTime*1000+nTotalTimeFrac*100;
594
  nMaxInactiveTime=nMaxInactiveTime*1000+nMaxInactiveTimeFrac*100;
595
  nActiveTimeout=nActiveTimeout*1000+nActiveTimeoutFrac*100;
596
  nDownloadTime=nDownloadTime*1000+nDownloadTimeFrac*100;
597
  nDownloadTimeout=nDownloadTimeout*1000+nDownloadTimeoutFrac*100;
598
 
599
  nFileSize*=1024;
600
  nDownloadedSize*=1024;
601
  t.tm_year-=1900;
602
  t.tm_mon--;
603
  return t.tm_year>=0 && t.tm_year<=200 && t.tm_mon>=0 && t.tm_mon<=11 && t.tm_mday>=1 && t.tm_mday<=31 && t.tm_hour>=0 && t.tm_hour<=23 && t.tm_min>=0 && t.tm_min<=59 && t.tm_sec>=0 && t.tm_sec<=59 &&
604
    status!=StatusTypeMax
605
    //&& exetype!=ExecutionParameters::ExecutableTypeMax
606
    ;
607
}
608
 
609
const String CeCosTest::ResultString(bool bIncludeOutput) const
610
{
611
  String strResultString;
612
  String strTitle(m_strTitle);
613
  String strExecutionHostPort(m_strExecutionHostPort);
614
 
615
  if(0==strTitle.size()){
616
    strTitle=CeCosSocket::MySimpleHostName();
617
    strTitle+=_TCHAR(':');
618
    strTitle+=m_strExecutable;
619
  }
620
 
621
  if(0==strExecutionHostPort.size()){
622
    strExecutionHostPort=CeCosSocket::MySimpleHostName();
623
    strExecutionHostPort+=_T(":0");
624
  }
625
 
626
  ENTERCRITICAL;
627
  time_t ltime;
628
  time(&ltime);
629
  struct tm *now=localtime( &ltime );
630
 
631
  strResultString.Format(
632
    pszFormat,
633
    1900+now->tm_year,1+now->tm_mon,now->tm_mday,
634
    now->tm_hour,now->tm_min,now->tm_sec,               // Time of day
635
    (LPCTSTR)strExecutionHostPort,                      // Execution host:port
636
    (LPCTSTR)m_ep.PlatformName(),                       // Target
637
    (LPCTSTR)CeCosTestUtils::Tail(m_strExecutable),     // Executable
638
    (LPCTSTR)Image(Status()),                           // Result
639
    m_nStrippedSize/1024,m_nFileSize/1024,              // Sizes
640
    WF(m_nDownloadTime),WF(m_ep.DownloadTimeout()),WF(m_nTotalTime),// Times
641
    WF(m_nMaxInactiveTime),WF(m_ep.ActiveTimeout()),
642
    (LPCTSTR)strTitle                                   // Title
643
    );
644
  if(bIncludeOutput && m_strOutput.size()>0){
645
    strResultString+=_TCHAR('\n');
646
    strResultString+=m_strOutput;
647
  }
648
  LEAVECRITICAL;
649
  return strResultString;
650
}
651
 
652
// Run as a server, listening on the port given as parameter
653
bool CeCosTest::RunAgent(int nTcpPort)
654
{
655
  bool bLocked=false;
656
 
657
  // Create socket
658
  int nSock = CeCosSocket::Listen(nTcpPort);
659
  int nLastClient=0;
660
  if (-1!=nSock) {
661
    for (;;) {
662
      try {
663
        CeCosSocket *pSock=new CeCosSocket(nSock); // AcceptThreadFunc deletes if not deleted below
664
        String str;
665
        // Read the execution parameters
666
        if(!pSock->recvString(str)){
667
          // Socket error on the recv - nothing much we can do
668
          TRACE(_T("RunAgent : could not read execution parameters\n"));
669
          delete pSock;
670
          pSock=0;
671
        } else {
672
          ExecutionParameters e;
673
          e.FromStr(str);
674
          TRACE(_T("Execution parameters: %s\n"),(LPCTSTR)e.Image());
675
          ServerStatus s;
676
          CTestResource *pPort=0;
677
          String strInfo;
678
 
679
          switch(e.Request()) {
680
            case ExecutionParameters::LOCK:
681
              if(bLocked){
682
                s=SERVER_BUSY;
683
              } else {
684
                WaitForAllInstances(1000,NOTIMEOUT);
685
                bLocked=true;
686
                s=SERVER_LOCKED;
687
              }
688
              break;
689
            case ExecutionParameters::UNLOCK:
690
              if(bLocked){
691
                bLocked=false;
692
                s=SERVER_READY;
693
              } else {
694
                s=SERVER_BUSY;
695
              }
696
              break;
697
            case ExecutionParameters::QUERY:
698
              if (bLocked) {
699
                s=SERVER_LOCKED;
700
              } else {
701
                s=SERVER_BUSY;
702
                ENTERCRITICAL;
703
                for(CTestResource *pResource=CTestResource::First();pResource;pResource=pResource->Next()){
704
                  if(!pResource->InUse()){
705
                    s=SERVER_READY;
706
                    break;
707
                  }
708
                }
709
                LEAVECRITICAL;
710
                if(SERVER_READY!=s){
711
                  strInfo.Format(_T("serving %s"),(LPCTSTR)CeCosSocket::ClientName(nLastClient));
712
                }
713
              }
714
              break;
715
            case ExecutionParameters::RUN:
716
              if(NULL==e.Platform()){
717
                // Looks like a confused client ...
718
                strInfo.Format(_T("Bad target value %s read from client\n"),(LPCTSTR)str);
719
                s=SERVER_CANT_RUN;
720
              } else if(0==CTestResource::Count(e)){
721
                // No chance of running this test
722
                strInfo.Format(_T("Cannot run a %s test from this server\n"),(LPCTSTR)e.PlatformName());
723
                s=SERVER_CANT_RUN;
724
              } else if (bLocked) {
725
                s=SERVER_LOCKED;
726
              } else {
727
                pPort=CTestResource::GetResource(e);
728
                if(0==pPort){
729
                  // We must disappoint our client
730
                  strInfo.Format(_T("serving %s"),(LPCTSTR)CeCosSocket::ClientName(nLastClient));
731
                  s=SERVER_BUSY;
732
                } else {
733
                  s=SERVER_READY;
734
                  nLastClient=pSock->Client();
735
                }
736
              }
737
              break;
738
            case ExecutionParameters::STOP:
739
              s=SERVER_READY;
740
              break;
741
            default:
742
              s=SERVER_CANT_RUN;
743
          }
744
 
745
#ifndef VERBOSE
746
          if(ExecutionParameters::QUERY!=e.Request())
747
#endif
748
            TRACE(_T("RunAgent : %s request tActive=%d tDownload=%d Target=%s Reply status=%s %s\n"),
749
              (LPCTSTR)e.Image(e.Request()),e.ActiveTimeout(),e.DownloadTimeout(),
750
              (LPCTSTR)e.PlatformName(),
751
              (LPCTSTR)Image(s),(LPCTSTR)strInfo);
752
 
753
          bool bSendok=pSock->sendInteger(s) && pSock->sendString(strInfo);
754
 
755
          if(SERVER_READY==s && bSendok && ExecutionParameters::RUN==e.Request()){
756
 
757
            // Create a new class instance
758
            // AcceptThreadFunc deletes the instance and closes new_sock
759
            // RunLocal, called by AcceptThreadFunc, releases the port
760
            // No need for meaningful callback, but must run asynchronously
761
 
762
            int nAuxPort=30000;
763
            int nAuxListenSock=-1;
764
 
765
            do {
766
              nAuxListenSock=CeCosSocket::Listen(nAuxPort);
767
            } while (-1==nAuxListenSock && nAuxPort++<=0xffff);
768
 
769
            if(-1==nAuxListenSock){
770
              ERROR(_T("Couldn't find a socket to bind to for RDI\n"));
771
            } else {
772
 
773
              CeCosTest *pTest=new CeCosTest(e,NULL);
774
              pTest->m_nAuxPort=nAuxPort;
775
              pTest->m_nAuxListenSock=nAuxListenSock;
776
              pTest->m_pSock=pSock;
777
              pTest->m_strExecutionHostPort=CeCosSocket::HostPort(CeCosSocket::MyHostName(),nTcpPort);
778
              pTest->m_pResource=pPort;
779
              CeCosThreadUtils::RunThread(SAcceptThreadFunc,pTest,_T("SAcceptThreadFunc"));
780
              // AcceptThreadFunc deletes pSock
781
            }
782
 
783
          } else {
784
            delete pSock;
785
            pSock=0;
786
            if(pPort){
787
              pPort->Release();
788
              pPort=0;
789
            }
790
            if(CeCosTest::ExecutionParameters::STOP==e.Request()){
791
              CancelAllInstances();
792
              WaitForAllInstances(1000,20*1000);
793
              break;
794
            }
795
          }
796
        }
797
      }
798
      catch(...){
799
        TRACE(_T("!!! Exception caught in RunAgent()\n"));
800
      }
801
    }
802
    CeCosSocket::CloseSocket (nSock);
803
  }
804
 
805
  return false;
806
}
807
 
808
CeCosTest::StatusType CeCosTest::StatusTypeValue(LPCTSTR  pszStr)
809
{
810
  for(int i=0;i<StatusTypeMax;i++){
811
    StatusType t=(StatusType)i;
812
    if(0==_tcsicmp(Image(t),pszStr)){
813
      return t;
814
    }
815
  }
816
  return StatusTypeMax;
817
}
818
 
819
// Thread to run ConnectSocketToSerial
820
void CeCosTest::ConnectSocketToSerialThreadFunc()
821
{
822
  TRACE(_T("ConnectSocketToSerialThreadFunc sock=%d\n"),m_nAuxListenSock);
823
 
824
  CeCosTestSerialFilter serial_filter;
825
  CeCosTestDownloadFilter download_filter;
826
 
827
  CeCosSerial serial;
828
  serial.SetBlockingReads(false);
829
  bool rc=false;
830
  // Open serial device.
831
  if (!serial.Open(m_pResource->Serial(),m_pResource->Baud())){
832
    ERROR(_T("Couldn't open port %s\n"),m_pResource->Serial());
833
  } else {
834
    for(;;){
835
      // Flush the serial buffer.
836
      serial.Flush();
837
      TRACE(_T("ConnectSocketToSerial: waiting for connection...\n"));
838
      CeCosSocket socket;
839
      if(!socket.Accept(m_nAuxListenSock,&m_bStopConnectSocketToSerial)){
840
        ERROR(_T("ConnectSocketToSerial - couldn't accept: %s\n"),(LPCTSTR)socket.SocketErrString());
841
        break;
842
      } else if (m_pSock->Client() != socket.Client()){
843
        // Make sure the client is who we think it is...
844
        TRACE(_T("ConnectSocketToSerialThread - illegal connection attempted from %s\n"),(LPCTSTR)socket.ClientName(socket.Client()));
845
      } else {
846
        try {
847
            rc=CeCosSocket::ConnectSocketToSerial(socket,serial,m_ep.m_bUseFilter?SerialFilterFunction:NULL, (void*)&serial_filter, m_ep.m_bUseFilter?DownloadFilterFunction:NULL, (void*)&download_filter, &m_bStopConnectSocketToSerial);
848
 
849
          // If the download filter was just active, it may
850
          // allow the session to continue.
851
          if(!download_filter.ContinueSession()){
852
            break;
853
          }
854
 
855
        }
856
        catch (LPCTSTR pszMsg){
857
          Log(_T("!!! ConnectSocketToSerial exception caught: %s!!!\n"),pszMsg);
858
          rc=false;
859
          break;
860
        }
861
        catch (...){
862
          Log(_T("!!! ConnectSocketToSerial exception caught!!!\n"));
863
          rc=false;
864
          break;
865
        }
866
      }
867
    }
868
  }
869
  TRACE(_T("ConnectSocketToSerial : done\n"));
870
  CeCosSocket::CloseSocket(m_nAuxListenSock);
871
}
872
 
873
static bool CALLBACK DerefBool(void *pParam)
874
{
875
  return *(bool *)pParam;
876
}
877
 
878
// Function called (on a separate thread) to process a successful connection to the RunAgent loop
879
// In the case of a simulator server, we can have many of these active at the same time.
880
void CeCosTest::AcceptThreadFunc()
881
{
882
  if(m_ep.Platform()->ServerSideGdb()){
883
    // We dream up a temporary name for the executable
884
    ENTERCRITICAL;
885
    m_strExecutable.Format(_T("%s-%s-%d"),_ttmpnam(0),(LPCTSTR)m_ep.PlatformName(),m_nAuxPort);
886
    LEAVECRITICAL;
887
 
888
    int n;
889
    if(m_pSock->recvInteger(n,_T("file size"))){
890
      m_nFileSize=n;
891
      // Read file from the socket
892
      bool bCanRun=true;
893
      TRACE(_T("AcceptThreadFunc file size=%d reading...\n"),m_nFileSize);
894
      FILE *f2;
895
      f2=_tfopen(m_strExecutable,_T("wb"));
896
      if(0==f2){
897
        Log(_T("Could not create %s - %s\n"),(LPCTSTR)m_strExecutable,strerror(errno));
898
        bCanRun=false;
899
      }
900
      unsigned int nBufSize=MIN(100000,m_nFileSize);
901
      Buffer b(nBufSize);
902
      unsigned int nWritten=0;
903
      unsigned int nRead=0;
904
      while(nRead<m_nFileSize){
905
        int nToRead=MIN(nBufSize,m_nFileSize-nRead);
906
        if(!recv( b.Data(), nToRead, _T("executable"))){
907
          break;
908
        }
909
        nRead+=nToRead;
910
        if(0!=f2){
911
          char *c=(char *)b.Data();
912
          while(nToRead>0){
913
            int w=fwrite(c,1,nToRead,f2);
914
            if(-1==w){
915
              Log(_T("Write error on %s - %s\n"),(LPCTSTR)m_strExecutable,strerror(errno));
916
              bCanRun=false;
917
              break;
918
            }
919
            nWritten+=w;
920
            c+=w;
921
            nToRead-=w;
922
          }
923
        }
924
      }
925
      TRACE(_T("Accept - done reading [%d bytes read, %d bytes written]\n"),nRead,nWritten);
926
      if(0!=f2){
927
        fclose(f2);
928
        _tchmod(m_strExecutable,00700); // user read, write and execute
929
      }
930
      if(0!=f2 && m_nFileSize!=nWritten){
931
        Log(_T("Failed to create %s correctly [%d/%d bytes written]\n"),(LPCTSTR)m_strExecutable, nWritten, m_nFileSize);
932
        bCanRun=false;
933
      }
934
      SetExecutable(m_strExecutable); // to set stripped length and title
935
      RunLocal();
936
      _tunlink(m_strExecutable);
937
    }
938
    sendResult();
939
    m_pSock->recvInteger(n); // receive an ack
940
  } else {
941
    // Client-side GDB
942
    bool bTargetReady;
943
    if(_TCHAR('\0')==*(m_pResource->ResetString())){
944
      bTargetReady=true;
945
      TRACE(_T("No reset possible\n"));
946
    } else {
947
      Log(_T("Resetting target using %s"),(LPCTSTR)m_pResource->ResetString());
948
      bTargetReady=(CResetAttributes::RESET_OK==m_pResource->Reset(ResetLogFunc,this));
949
    }
950
    TRACE(_T("Send Target Ready indicator=%d\n"),bTargetReady);
951
    m_pSock->sendInteger(bTargetReady,_T("target ready indicator"));
952
 
953
    int nAck=-1;
954
 
955
    if(bTargetReady){
956
      if(CeCosSocket::IsLegalHostPort(m_pResource->Serial())){
957
        TRACE(_T("Sending %s\n"),(LPCTSTR)m_pResource->Serial());
958
        if(m_pSock->sendString(m_pResource->Serial(),_T("Serial name")) && m_pSock->recvInteger(nAck,_T("Terminating ack"),CeCosSocket::NOTIMEOUT)){
959
          TRACE(_T("Terminating ack=%d\n"),nAck);
960
        }
961
      } else {
962
        String strHostPort(CeCosSocket::HostPort(CeCosSocket::MyHostName(),m_nAuxPort));
963
 
964
        TRACE(_T("Using %s\n"),(LPCTSTR)strHostPort);
965
 
966
        if(m_pSock->sendString(strHostPort,_T("host:port"))){
967
 
968
          // This Boolean signifies that the serial<-->tcp/ip conversation is done.  It may be set
969
          // on completion of the ConnectSocketToSerial thread (which is why we pass it to runthread)
970
          // and also set by us to *cause* the thread to complete.
971
 
972
          bool bConnectSocketToSerialThreadDone=false; // Indication of termination of ConnectSocketToSerial thread
973
          m_bStopConnectSocketToSerial=false; // Used to tap ConnectSocketToSerial thread on the shoulder
974
 
975
          CeCosThreadUtils::RunThread(SConnectSocketToSerialThreadFunc,this,&bConnectSocketToSerialThreadDone,_T("SConnectSocketToSerialThreadFunc"));
976
 
977
          // Wait for either client or the ConnectSocketToSerial thread to finish.
978
          if(m_pSock->recv(&nAck,sizeof(int),_T("Terminating ack"),CeCosSocket::NOTIMEOUT,DerefBool,&bConnectSocketToSerialThreadDone)){
979
            TRACE(_T("Session terminated by request of client (%s)\n"),(LPCTSTR)Image((StatusType)nAck));
980
          } else if(0!=m_pSock->SocketError()){
981
            TRACE(_T("Session terminated by socket error - %s\n"),(LPCTSTR)m_pSock->SocketErrString());
982
          }
983
          if(!bConnectSocketToSerialThreadDone){
984
            // Tap ConnectSocketToSerial thread on the shoulder
985
            TRACE(_T("Waiting for ConnectSocketToSerial thread to terminate...\n"));
986
            m_bStopConnectSocketToSerial=true;
987
            CeCosThreadUtils::WaitFor(bConnectSocketToSerialThreadDone);
988
          }
989
        }
990
      }
991
    }
992
  }
993
  delete this;
994
}
995
 
996
bool CeCosTest::send(const void *pData,unsigned int nLength,LPCTSTR pszMsg,Duration dTimeout)
997
{
998
  return m_pSock->send(pData,nLength,pszMsg,dTimeout,IsCancelled,this);
999
}
1000
 
1001
bool CeCosTest::recv(const void *pData,unsigned int nLength,LPCTSTR pszMsg,Duration dTimeout)
1002
{
1003
  return m_pSock->recv(pData,nLength,pszMsg,dTimeout,IsCancelled,this);
1004
}
1005
 
1006
void CeCosTest::Log(LPCTSTR  pszFormat, ...)
1007
{
1008
  va_list args;
1009
  va_start(args, pszFormat);
1010
  String str;
1011
  str.vFormat(pszFormat,args);
1012
  va_end(args);
1013
  LogString(str);
1014
}
1015
 
1016
void CeCosTest::LogString(LPCTSTR psz)
1017
{
1018
  if(*psz){
1019
    ENTERCRITICAL;
1020
    m_strOutput+=psz;
1021
    LEAVECRITICAL;
1022
    if(CeCosTrace::IsInteractive()){
1023
      CeCosTrace::Out(psz);
1024
    } else {
1025
      TRACE(_T("%s"),psz);
1026
    }
1027
  }
1028
}
1029
 
1030
bool CeCosTest::sendResult(Duration dTimeout)
1031
{
1032
  bool rc=
1033
    m_pSock->sendInteger(m_Status,_T("result"),dTimeout) &&
1034
    m_pSock->sendInteger(m_nDownloadTime,_T("result"),dTimeout) &&
1035
    m_pSock->sendInteger(m_nTotalTime,_T("result"),dTimeout) &&
1036
    m_pSock->sendInteger(m_nMaxInactiveTime,_T("result"),dTimeout) &&
1037
    m_pSock->sendString (m_strOutput,_T("result"),dTimeout);
1038
  return rc;
1039
}
1040
 
1041
bool CeCosTest::recvResult(Duration dTimeout)
1042
{
1043
  String strOutput;
1044
  int nStatus=StatusTypeMax;
1045
  bool rc=
1046
    m_pSock->recvInteger(nStatus,_T("result"),dTimeout) &&
1047
    m_pSock->recvInteger(m_nDownloadTime,_T("result"),dTimeout) &&
1048
    m_pSock->recvInteger(m_nTotalTime,_T("result"),dTimeout) &&
1049
    m_pSock->recvInteger(m_nMaxInactiveTime,_T("result"),dTimeout) &&
1050
    m_pSock->recvString (strOutput,_T("result"),dTimeout);
1051
  m_Status=(StatusType)MIN(nStatus,StatusTypeMax);
1052
  LogString(strOutput);
1053
  return rc;
1054
}
1055
 
1056
// Return time used by inferior gdb process - CPU for sim, wallclock otherwise
1057
Time CeCosTest::InferiorTime() const
1058
{
1059
  if(*(m_pResource->Serial())){
1060
    return Now();
1061
  }
1062
  if(!m_psp){
1063
    return 0;
1064
  }
1065
  Time now=Now();
1066
  if(now-m_tPrevSample>1000){
1067
    m_tPrevSample=now;
1068
    m_tInferiorCpuTime=m_psp->CpuTime();
1069
  }
1070
  return m_tInferiorCpuTime;
1071
}
1072
 
1073
bool CeCosTest::CheckForTimeout()
1074
{
1075
  bool rc=(Cancelled!=Status());
1076
  if(TimeOut!=m_Status && DownloadTimeOut!=m_Status){
1077
    Time t=InferiorTime();
1078
    if(t){
1079
      // We have been able to measure the time
1080
      if(m_bDownloading){
1081
        m_nDownloadTime=MAX(m_nDownloadTime,Duration(InferiorTime()-m_tBase));
1082
        if(m_nDownloadTime>m_ep.DownloadTimeout()){
1083
          Log(_T("\n*** Timeout - download time ") WFS _T(" exceeds limit of ") WFS _T("\n"),WF(m_nDownloadTime),WF(m_ep.DownloadTimeout()));
1084
          rc=false;
1085
        }
1086
      } else {
1087
        m_nMaxInactiveTime=MAX(m_nMaxInactiveTime,Duration(InferiorTime()-m_tBase));
1088
        if (m_nMaxInactiveTime>m_ep.ActiveTimeout()) {
1089
          Log(_T("\n*** Timeout - inactive time ") WFS _T(" exceeds limit of ") WFS _T("\n"),WF(m_nMaxInactiveTime),WF(m_ep.ActiveTimeout()));
1090
          rc=false;
1091
        }
1092
      }
1093
    }
1094
    m_nTotalTime=Duration(Now()-m_tWallClock0);
1095
/*
1096
    if(m_nTotalTime>m_ep.ElapsedTimeout()){
1097
      Log(_T("\n*** Timeout - total time ") WFS _T(" exceeds limit of ") WFS _T("\n"),   WF(m_nTotalTime),WF(m_ep.ElapsedTimeout()));
1098
      rc=false;
1099
    }
1100
*/
1101
    if(!rc){
1102
      SetStatus(m_bDownloading?DownloadTimeOut:TimeOut);
1103
    }
1104
  }
1105
  return rc;
1106
}
1107
 
1108
// Convert a path to something a cygwin tool will understand.  Used when invoking -size and -gdb
1109
String CeCosTest::CygPath (LPCTSTR pszPath)
1110
{
1111
#ifdef _WIN32
1112
  String str = "";
1113
  HKEY hKey = 0;
1114
  DWORD type;
1115
  BYTE value[256];
1116
  DWORD sz = sizeof(value);
1117
 
1118
  // look for the cygdrive prefix in the user's registry settings
1119
  if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Cygnus Solutions\\Cygwin\\mounts v2", 0, KEY_READ, &hKey)) {
1120
    if (ERROR_SUCCESS == RegQueryValueEx(hKey, "cygdrive prefix", NULL, & type, value, & sz)) {
1121
      str = (const char*) value;
1122
    }
1123
    RegCloseKey(hKey);
1124
  }
1125
 
1126
  // if not yet found, look for the cygdrive prefix in the system registry settings
1127
  hKey = 0;
1128
  sz = sizeof(value);
1129
  if (str.empty() && (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Cygnus Solutions\\Cygwin\\mounts v2", 0, KEY_READ, &hKey))) {
1130
    if (ERROR_SUCCESS == RegQueryValueEx(hKey, "cygdrive prefix", NULL, & type, value, & sz)) {
1131
      str = (const char*) value;
1132
    }
1133
    RegCloseKey(hKey);
1134
  }
1135
 
1136
  int prefixlen = str.length();
1137
  TCHAR *buf=str.GetBuffer(prefixlen+1+MAX_PATH);
1138
  TCHAR *pszFname;
1139
  if(::GetFullPathName(pszPath,MAX_PATH,prefixlen+buf, &pszFname)){
1140
    GetShortPathName(prefixlen+buf,prefixlen+buf,MAX_PATH); // ignore errors
1141
    buf[prefixlen+1]=buf[prefixlen];
1142
    buf[prefixlen]=_TCHAR('/');
1143
    for(int i=prefixlen+2;buf[i];i++){
1144
      if(_TCHAR('\\')==buf[i]){
1145
        buf[i]=_TCHAR('/');
1146
      }
1147
    }
1148
    str.ReleaseBuffer();
1149
    return str;
1150
  } else {
1151
    str.ReleaseBuffer();
1152
    return pszPath;
1153
  }
1154
#endif
1155
  return pszPath;
1156
}
1157
 
1158
void CeCosTest::SetExecutable(LPCTSTR pszExecutable)
1159
{
1160
  m_strOutput=_T("");
1161
  if(pszExecutable){
1162
    m_strExecutable=pszExecutable;
1163
    if(m_ep.Platform()){
1164
      GetSizes();
1165
    } else {
1166
      ERROR(_T("Don't know how to get sizes of this platform type\n"));
1167
    }
1168
  } else {
1169
    m_strExecutable=_T("");
1170
  }
1171
}
1172
 
1173
// Calculate the sizes of the given file.  The target parameter is necessary in order to 
1174
// determine which -size executable to use to do the job.
1175
bool CeCosTest::GetSizes()
1176
{
1177
TRACE(_T("GetSizes %s\n"),(LPCTSTR)Executable());
1178
  bool rc=false;
1179
  m_nStrippedSize=m_nFileSize=0;
1180
  LPCTSTR pszPrefix=m_ep.Platform()->Prefix();
1181
  struct _stat buf;
1182
  if(-1==_tstat(Executable(),&buf)){
1183
    Log(_T("%s does not exist\n"),(LPCTSTR)Executable());
1184
  } else if (_TCHAR('\0')==*pszPrefix){
1185
    LogString(_T("No prefix to run a size program\n"));
1186
  } else {
1187
    m_nFileSize=buf.st_size;
1188
    const String strSizeCmd(String::SFormat(_T("%s-size %s"),pszPrefix,(LPCTSTR)CygPath(Executable())));
1189
    String strOut;
1190
    CSubprocess sp;
1191
    if(!sp.Run(strOut,strSizeCmd)){
1192
      Log(_T("Failed to run \"%s\" - %s\n"),(LPCTSTR)strSizeCmd,(LPCTSTR)sp.ErrorString());
1193
    } else {
1194
      const TCHAR *c=_tcschr(strOut,_TCHAR('\n'));
1195
      if(c){
1196
        c++;
1197
      }
1198
      int s1=0;
1199
      int s2=0;
1200
      if(c && 2==_stscanf(c,_T(" %d %d"),&s1,&s2)){
1201
        rc=true;
1202
        m_nStrippedSize=s1+s2;
1203
      }
1204
      TRACE(_T("GetSizes %s rc=%d file size=%d stripped size=%d\n"),(LPCTSTR)Executable(),rc,m_nFileSize,m_nStrippedSize);
1205
    }
1206
  }
1207
  return rc;
1208
}
1209
 
1210
void CeCosTest::SetTimeouts (Duration dActive,Duration dDownload/*,Duration dElapsed*/)
1211
{
1212
  m_ep.SetActiveTimeout  (dActive);
1213
  m_ep.SetDownloadTimeout(dDownload);
1214
/*
1215
  m_ep.SetElapsedTimeout (dElapsed);
1216
*/
1217
}
1218
 
1219
void CeCosTest::CloseSocket (){
1220
  delete m_pSock;
1221
  m_pSock=0;
1222
}
1223
 
1224
bool CeCosTest::AtPrompt()
1225
{
1226
  const String strPrompt(m_ep.Platform()->Prompt());
1227
  unsigned int nPromptLen=_tcslen(strPrompt);
1228
  return
1229
    nPromptLen>0 &&
1230
    m_strOutput.size()>=nPromptLen &&
1231
    0==_tcscmp((LPCTSTR)m_strOutput+m_strOutput.size()-nPromptLen,strPrompt);
1232
}
1233
 
1234
#ifdef _WIN32
1235
BOOL WINAPI HandlerRoutine(
1236
                           DWORD dwCtrlType   //  control signal type
1237
                           )
1238
{
1239
  dwCtrlType; // eliminate compiler warning
1240
  return TRUE;
1241
}
1242
#endif
1243
 
1244
 
1245
bool CeCosTest::InteractiveInferior(LPCTSTR pszHostPort,TCHAR **argv)
1246
{
1247
  bool rc=false;
1248
  if(_TCHAR('\0')!=*pszHostPort){
1249
    if(!CeCosSocket::IsLegalHostPort(pszHostPort)){
1250
      ERROR(_T("Illegal host:port '%s'\n"),pszHostPort);
1251
      return false;
1252
    } else {
1253
      m_strExecutionHostPort=pszHostPort;
1254
      Log(_T("Waiting to connect to %s...\n"),(LPCTSTR)m_strExecutionHostPort);
1255
    }
1256
  } else {
1257
    Log(_T("Waiting to connect to a server...\n"));
1258
  }
1259
 
1260
  ConnectForExecution();
1261
 
1262
  Log(_T("Connected to %s - waiting for target reset\n"),(LPCTSTR)m_strExecutionHostPort);
1263
  String strHostPort,strOutput;
1264
  // We read:
1265
  //     target ready indicator
1266
  //     any output so far
1267
  //     (if target ready) host:port
1268
  if(GetTargetReady(strHostPort)){
1269
    Log(_T("Use target remote %s\n"),(LPCTSTR)strHostPort);
1270
    String strInferior(m_ep.Platform()->Prefix());
1271
    strInferior+=_T("-gdb");
1272
#ifdef _WIN32
1273
    SetConsoleCtrlHandler(HandlerRoutine,TRUE);
1274
    int n=_tspawnvp(_P_WAIT,strInferior,argv);
1275
    if(-1==n){
1276
      Log(_T("Failed to spawn %s\n"),(LPCTSTR)strInferior);
1277
    } else {
1278
      rc=(0==n);
1279
    }
1280
    SetConsoleCtrlHandler(HandlerRoutine,FALSE);
1281
#else // UNIX
1282
 
1283
    int pid=fork();
1284
    switch(pid){
1285
    case -1:
1286
      _ftprintf(stderr,_T("fork failed\n"));
1287
      pid=0;
1288
      break;
1289
    case 0:
1290
      // Process is created (we're the child)
1291
      execvp(strInferior,argv);
1292
      Log(_T("Error invoking %s - %s\n"),(LPCTSTR)strInferior,strerror(errno));
1293
      exit(1);
1294
      break;
1295
    default:
1296
      // Process is created (we're the parent)
1297
      {
1298
        signal(SIGINT,SIG_IGN);
1299
        int stat;
1300
        waitpid(pid,&stat,0);
1301
        rc=(0==stat);
1302
        signal(SIGINT,SIG_DFL);
1303
      }
1304
      break;
1305
    }
1306
#endif
1307
    Log(_T("Inferior terminated\n"));
1308
    // Tell the server we're through
1309
    m_pSock->sendInteger(123,_T("Terminating ack"));
1310
  }
1311
  return rc;
1312
}
1313
 
1314
void CALLBACK CeCosTest::ResetLogFunc(void *pParam, LPCTSTR psz)
1315
{
1316
  CeCosTest *pTest=(CeCosTest *)pParam;
1317
  TRACE(_T("Send Target Ready indicator=2\n"));
1318
  pTest->m_pSock->sendInteger(2,_T("target ready indicator"));
1319
  TRACE(_T("Send %s\n"),psz);
1320
  pTest->m_pSock->sendString(psz,_T("output so far"));
1321
}
1322
 
1323
CeCosTest::ExecutionParameters::RequestType CeCosTest::ExecutionParameters::RequestTypeValue(LPCTSTR psz)
1324
{
1325
  int r;
1326
  for(r=0;r<RequestTypeMax;r++){
1327
    if(0==_tcsicmp(psz,arRequestImage[r])){
1328
      break;
1329
    }
1330
  }
1331
  return (RequestType)r;
1332
}
1333
 
1334
void CeCosTest::InferiorOutputFunc(LPCTSTR pszMsg)
1335
{
1336
  LogString(pszMsg);
1337
 
1338
  m_nOutputLen+=_tcslen(pszMsg);
1339
 
1340
  if(m_pspPipe){
1341
    m_pspPipe->Send(pszMsg);
1342
  }
1343
 
1344
  if(m_nOutputLen>20000){
1345
    LogString(_T("\n>>>> Infra FAIL\n*** too much output ***\n>>>>\n"));
1346
    SetStatus(Fail);
1347
    m_psp->Kill();
1348
  }
1349
 
1350
  m_tBase=InferiorTime(); // We are seeing life, so reset the clock for timeouts
1351
 
1352
  if(AtPrompt()){
1353
 
1354
    // gdb's output included one or more prompts
1355
    // Send another command along
1356
    if(m_nCmdIndex>=m_arstrInferiorCmds.size()){
1357
      // Nothing further to say to gdb - exit
1358
 
1359
      m_psp->Kill(); // case 3
1360
    } else {
1361
 
1362
      if(m_nCmdIndex>0 && 0==_tcscmp(_T("load"),m_arstrInferiorCmds[m_nCmdIndex-1])){
1363
        // load command was previous command - we are no longer downloading
1364
        m_bDownloading=false;
1365
      }
1366
 
1367
      String strCmd(m_arstrInferiorCmds[m_nCmdIndex++]);
1368
 
1369
      // If we can there is a GDB instruction to send to gdb, do it
1370
      String str;
1371
      if(GetDirective(_T("GDB:"),str,m_nLastGdbInst)){
1372
        strCmd=str;
1373
        m_nCmdIndex--; // undo increment above
1374
      }
1375
 
1376
      if(0==_tcscmp(_T("load"),strCmd)){
1377
        // load command issued - we are now "downloading"
1378
        m_bDownloading=true;
1379
      } else if(0==_tcscmp(_T("run"),strCmd) || 0==_tcscmp(_T("cont"),strCmd)){
1380
        SetStatus(NoResult);
1381
      }
1382
 
1383
      strCmd+=_TCHAR('\n');
1384
      LogString(strCmd);
1385
      m_psp->Send(strCmd);
1386
 
1387
    }
1388
  }
1389
 
1390
  // If there is a EXEC instruction to process, obey it
1391
  String strCmd;
1392
  while(GetDirective(_T("EXEC:"),strCmd,m_nLastExecInst)){
1393
    CSubprocess *pExecsp=new CSubprocess;
1394
    pExecsp->SetPath(m_strPath);
1395
    if(!pExecsp->Run(AppendFunc,this,(LPCTSTR)strCmd,false)){
1396
      Log(_T("%%%% Failed to create process '%s'\n"),(LPCTSTR)strCmd);
1397
      delete pExecsp;
1398
    } else {
1399
      m_arpExecsp.push_back(pExecsp);
1400
    }
1401
  }
1402
 
1403
  // If there is a PIPE instruction to process, obey it
1404
  while(GetDirective(_T("PIPE:"),strCmd,m_nLastPipeInst)){
1405
    if(m_pspPipe){
1406
      Log(_T("%%%% Two PIPE commands are a no-no\n"));
1407
    } else {
1408
      m_pspPipe=new CSubprocess;
1409
      m_pspPipe->SetPath(m_strPath);
1410
 
1411
      if(!m_pspPipe->Run(AppendFunc,this,(LPCTSTR)strCmd,false)){
1412
        Log(_T("%%%% Failed to create process '%s'\n"),(LPCTSTR)strCmd);
1413
        delete m_pspPipe;
1414
        m_pspPipe=0;
1415
      } else {
1416
        // Send what we read have so far
1417
        m_pspPipe->Send(m_strOutput);
1418
      }
1419
    }
1420
  }
1421
 
1422
  while(GetDirective(_T("TIMEOUT:"),strCmd,m_nLastTimeoutInst)){
1423
    int n=_ttoi(strCmd);
1424
    if(n){
1425
      SetTimeouts(n); // second parameter is download timeout, which is now irrelevant
1426
    } else {
1427
      Log(_T("%%%% Illegal timeout specified: %s\n"),(LPCTSTR)strCmd);
1428
    }
1429
  }
1430
}
1431
 
1432
void CeCosTest::RunInferior(LPCTSTR pszCmdline)
1433
{
1434
  m_psp=new CSubprocess;
1435
  m_psp->SetContinuationFunc(SCheckForTimeout,this);
1436
  try {
1437
    m_nMaxInactiveTime=0;
1438
    m_nTotalTime=0;
1439
    m_nDownloadTime=0;
1440
    m_nOutputLen=0;
1441
    m_bDownloading=false;
1442
 
1443
    // Decide on the baseline status - NotStarted if there is a download element, NoResult otherwise.
1444
    m_Status=NoResult;
1445
    for(unsigned int i=0;i<m_arstrInferiorCmds.size();i++){
1446
      if(0==_tcscmp(_T("run"),m_arstrInferiorCmds[i]) || 0==_tcscmp(_T("cont"),m_arstrInferiorCmds[i])){
1447
        m_Status=NotStarted;
1448
        break;
1449
      }
1450
    }
1451
    TRACE(_T("Status <- %s\n"),(LPCTSTR)Image(m_Status));
1452
 
1453
    m_tPrevSample=0; // force an initial reading
1454
    m_tInferiorCpuTime=0;
1455
 
1456
    m_tBase=m_tBase0=InferiorTime(); // Returns either Now() or nothing
1457
    m_tWallClock0=Now();
1458
 
1459
    m_nCmdIndex=0;
1460
 
1461
    TRACE(_T("RunGDB()\n"));
1462
 
1463
    m_nLastGdbInst=m_nLastExecInst=m_nLastTimeoutInst=m_nLastPipeInst=0;
1464
    m_psp->SetPath(m_strPath);
1465
    if(m_psp->Run(SInferiorOutputFunc,this,pszCmdline,true)){
1466
 
1467
      if(m_pspPipe){
1468
        m_pspPipe->Send(_T("\n"));
1469
        m_pspPipe->CloseInput();
1470
        if(m_pspPipe->Wait(5000)){
1471
          // OK the pipe process terminated.
1472
          int rc=m_pspPipe->GetExitCode();
1473
          if(0!=rc){
1474
            Log(_T("%%%% Pipe process returned rc=%d\n"),rc);
1475
            SetStatus(Fail);
1476
          }
1477
        } else {
1478
          LogString(_T("%%%% Pipe process would not complete\n"));
1479
        }
1480
      }
1481
 
1482
      AnalyzeOutput();
1483
 
1484
    } else {
1485
      Log(_T("Failed to run \"%s\" - %s\n"),pszCmdline,(LPCTSTR)m_psp->ErrorString());
1486
    }
1487
  }
1488
  catch(...){
1489
    ERROR(_T("!!! Exception caught in RunInferior()\n"));
1490
  }
1491
  delete m_psp; // will cause process to be killed as necessary and completion to be waited for
1492
  m_psp=NULL;
1493
  for(int i=0;i<(signed)m_arpExecsp.size();i++){
1494
    delete (CSubprocess *)m_arpExecsp[i]; // ditto
1495
  }
1496
  m_arpExecsp.clear();
1497
  TRACE(_T("Exiting RunInferior()\n"));
1498
}
1499
 
1500
void CeCosTest::AnalyzeOutput()
1501
{
1502
  // This test is pulled out to allow ser_filter to simulate a test failure
1503
  if(OutputContains(_T("FAIL:"))){
1504
    SetStatus(Fail);
1505
  }
1506
 
1507
  if(OutputContains(_T("EXIT:"))||OutputContains(_T("NOTAPPLICABLE:"))){
1508
    static LPCTSTR arpszKeepAlive[]={_T("FAIL:"),_T("NOTAPPLICABLE:"), _T("PASS:")};
1509
    static const StatusType arStatus[] ={Fail, Inapplicable, Pass};
1510
    for(unsigned int i=0;i<sizeof arpszKeepAlive/sizeof arpszKeepAlive[0];i++){
1511
      if(OutputContains(arpszKeepAlive[i])){
1512
        TRACE(_T("DriveInferior: saw '%s'\n"),arpszKeepAlive[i]);
1513
        SetStatus(arStatus[i]); // Do not break!
1514
      }
1515
    }
1516
  }
1517
 
1518
  // Certain output spells failure...
1519
  if(OutputContains(_T("cyg_assert_fail ("))){
1520
    SetStatus(AssertFail);
1521
  } else {
1522
    static LPCTSTR arpszSignals[]={_T("SIGBUS"), _T("SIGSEGV"), _T("SIGILL"), _T("SIGFPE"), _T("SIGSYS"), _T("SIGTRAP")};
1523
    for(unsigned int i=0;i<sizeof arpszSignals/sizeof arpszSignals[0];i++){
1524
      String str1,str2;
1525
      str1.Format(_T("signal %s"),arpszSignals[i]);
1526
      str2.Format(_T("handle %s nostop"),arpszSignals[i]);
1527
      if(OutputContains(str1)&&!OutputContains(str2)){
1528
        SetStatus(Fail);
1529
        break;
1530
      }
1531
    }
1532
  }
1533
 
1534
  int nIndex=0;
1535
  String str;
1536
  while(GetDirective(_T("EXPECT:"),str,nIndex)){
1537
    // s1 is the pointer to the text following the expect - that to be tested
1538
    LPCTSTR s1=(LPCTSTR)m_strOutput+nIndex;
1539
    while (_istspace(*s1)){
1540
      s1++;
1541
    }
1542
    // whereas s2 is the pointer to the text in the expect string (what we are expecting)
1543
    LPCTSTR s2=(LPCTSTR)str;
1544
    while(*s2){
1545
      if(*s2!=*s1){
1546
        Log(_T("EXPECT:<> failure - expected '%s' saw '%s'\n"),(LPCTSTR)str,(LPCTSTR)m_strOutput+nIndex);
1547
        SetStatus(Fail);
1548
        break;
1549
      }
1550
      s1++;
1551
      s2++;
1552
    }
1553
  }
1554
}
1555
 
1556
bool CeCosTest::ExecutionParameters::FromStr(LPCTSTR psz)
1557
{
1558
  String str1,str2,str3,str4,str5;
1559
  int nUseFilter,nUnused2,nUnused3;
1560
  int nLen=_tcslen(psz);
1561
  _stscanf(psz,_T("%s %s %d %d %d %d %d %d %d %d %s %s %s"),
1562
    str1.GetBuffer(1+nLen),
1563
    str2.GetBuffer(1+nLen),
1564
    &m_nActiveTimeout,
1565
    &m_nDownloadTimeout,
1566
    &m_nUnused1,
1567
    &m_nUnused2,
1568
    &m_nUnused3,
1569
    &nUseFilter,
1570
    &nUnused2,
1571
    &nUnused3,
1572
    str3.GetBuffer(1+nLen),
1573
    str4.GetBuffer(1+nLen),
1574
    str5.GetBuffer(1+nLen)
1575
    );
1576
  m_bUseFilter=(0!=nUseFilter);
1577
  m_bUnused2=(0!=nUnused2);
1578
  m_bUnused3=(0!=nUnused3);
1579
  str1.ReleaseBuffer();
1580
  str2.ReleaseBuffer();
1581
  str3.ReleaseBuffer();
1582
  str4.ReleaseBuffer();
1583
  str5.ReleaseBuffer();
1584
  m_Target=str1;
1585
  int r;
1586
  for(r=0;r<RequestTypeMax;r++){
1587
    if(0==_tcscmp(arRequestImage[r],str2)){
1588
      break;
1589
    }
1590
  }
1591
  m_Request=(RequestType)r;
1592
  return CeCosTestPlatform::IsValid(m_Target);
1593
}
1594
 
1595
CeCosTest::ExecutionParameters::ExecutionParameters (RequestType r,
1596
                                                     LPCTSTR  Target,
1597
                                                     Duration    nActiveTimeout/*=NOTIMEOUT*/,
1598
                                                     Duration    nDownloadTimeout/*=NOTIMEOUT*/):
1599
  m_bUseFilter(true),
1600
  m_Target(Target),
1601
  m_nActiveTimeout(nActiveTimeout),
1602
  m_nDownloadTimeout(nDownloadTimeout),
1603
  m_Request(r),
1604
  m_nUnused1(0),
1605
  m_nUnused2(0),
1606
  m_nUnused3(0),
1607
  m_bUnused2(false),
1608
  m_bUnused3(false)
1609
{
1610
}
1611
 
1612
String CeCosTest::ExecutionParameters::Image() const
1613
{
1614
  String str;
1615
  str.Format(_T("%s %s %d %d %d %d %d %d %d %d"),(LPCTSTR)PlatformName(),(LPCTSTR)Image(Request()),
1616
    ActiveTimeout(),DownloadTimeout(),
1617
    m_nUnused1,
1618
    m_nUnused2,
1619
    m_nUnused3,
1620
    m_bUseFilter,
1621
    m_bUnused2,
1622
    m_bUnused3);
1623
  return str;
1624
}
1625
 
1626
bool CeCosTest::GetTargetReady(String &strHostPort)
1627
{
1628
  bool rc=false;
1629
  int nTargetReady;
1630
  do{
1631
    if(!m_pSock->recvInteger(nTargetReady,_T("Target ready"),120*1000)){
1632
      Log(_T("Failed to read target ready indicator from server - %s\n"),(LPCTSTR)m_pSock->SocketErrString());
1633
      break;
1634
    }
1635
    switch(nTargetReady){
1636
    case 0:
1637
      LogString(_T("Failed to reset target"));
1638
      break;
1639
    case 1:
1640
      if(m_pSock->recvString(strHostPort, _T("host:port"))){
1641
        TRACE(_T("Instructed to use %s\n"),(LPCTSTR)strHostPort);
1642
        rc=true;
1643
      } else {
1644
        Log(_T("Failed to read host:port - %s\n"),(LPCTSTR)m_pSock->SocketErrString());
1645
      }
1646
      break;
1647
    case 2:
1648
      {
1649
        String strOutput;
1650
        if(m_pSock->recvString(strOutput, _T("output"))){
1651
          LogString(strOutput);
1652
        } else {
1653
          Log(_T("Failed to read output\n"),(LPCTSTR)m_pSock->SocketErrString());
1654
          return false;
1655
        }
1656
      }
1657
      break;
1658
    }
1659
  } while(2==nTargetReady);
1660
  return rc;
1661
}
1662
 
1663
 
1664
CeCosTest::ServerStatus CeCosTest::ServerStatusValue(LPCTSTR psz)
1665
{
1666
  int s;
1667
  for(s=0;s<ServerStatusMax;s++){
1668
    if(0==_tcsicmp(psz,arServerStatusImage[s])){
1669
      break;
1670
    }
1671
  }
1672
  return (ServerStatus)s;
1673
 
1674
}
1675
 
1676
// Gets a directive from the test output (like EXEC:)
1677
bool CeCosTest::GetDirective(LPCTSTR pszDirective, String &str, int &nIndex)
1678
{
1679
  bool rc=false;
1680
  ENTERCRITICAL;
1681
  LPCTSTR pszOutput=(LPCTSTR)m_strOutput;
1682
  LPCTSTR pc=_tcsstr(pszOutput+nIndex,pszDirective);
1683
  if(pc){
1684
 
1685
    pc+=_tcslen(pszDirective); // Now after the final character (':') of the directive
1686
    if(_TCHAR('<')==*pc){
1687
 
1688
      pc++;
1689
 
1690
      // Extract the argument
1691
      str=_T("");
1692
      while(*pc){
1693
        // Process escapes: FIXME more escapes?
1694
        TCHAR c=*pc;
1695
        if(_TCHAR('\\')==c){
1696
          switch(pc[1]){
1697
            case _TCHAR('t'):
1698
              c=_TCHAR('\t');
1699
              break;
1700
            case _TCHAR('n'):
1701
              c=_TCHAR('\n');
1702
              break;
1703
            case _TCHAR('\0'):
1704
              pc--; // avoid grief
1705
              break;
1706
            default:
1707
              c=pc[1];
1708
              break;
1709
          }
1710
          pc++;
1711
        } else if (_TCHAR('>')==c) {
1712
          nIndex=pc+1-pszOutput;
1713
          rc=true;
1714
          break;
1715
        } else if (_TCHAR('\n')==c) {
1716
          nIndex=pc+1-pszOutput;
1717
          Log(_T("%%%% Unterminated directive: %s"),(LPCTSTR)str);
1718
          break;
1719
        }
1720
        str+=c;
1721
        pc++;
1722
      }
1723
    }
1724
  }
1725
  LEAVECRITICAL;
1726
  return rc;
1727
}
1728
 
1729
void CeCosTest::GetInferiorCommands(StringArray &arstrInferiorCmds)
1730
{
1731
  arstrInferiorCmds.clear();
1732
 
1733
  // Construct commands for gdb.  The commands may be found (semicolon-separated) in the target info:
1734
  const String strInferiorCmds(m_ep.Platform()->GdbCmds());
1735
  StringArray ar;
1736
  int nCmds=strInferiorCmds.Chop(ar,_TCHAR(';'),false);
1737
  for(int i=0;i<nCmds;i++){
1738
    // Into each command must be substituted:
1739
    // Baud rate (%b)  
1740
    // Port      (%p)  This will be a serial port (e.g. COM1) or a socket connection (e.g.aloo:8000) depending on circumstances.
1741
    // and escapes must be dealt with.
1742
    String strCmd;
1743
    for(const TCHAR *pc=ar[i];*pc;pc++){
1744
      switch(*pc){
1745
        // Process escapes: FIXME more escapes?
1746
        case _TCHAR('\\'):
1747
          switch(pc[1]){
1748
            case _TCHAR('t'):
1749
              strCmd+=_TCHAR('\t');
1750
              pc++;
1751
              continue;
1752
            case _TCHAR('n'):
1753
              strCmd+=_TCHAR('\n');
1754
              pc++;
1755
              continue;
1756
            case _TCHAR('\0'):
1757
              continue;
1758
            default:
1759
              break;
1760
          }
1761
          break;
1762
        case _TCHAR('%'):
1763
          switch(pc[1]){
1764
            case _TCHAR('%'):
1765
              strCmd+=_TCHAR('%');
1766
              pc++;
1767
              break;
1768
            case _TCHAR('b'):
1769
              if(0==m_pResource->Baud()){
1770
                goto NextCmd; // Suppress output of this command if there is no baud rate to output
1771
              }
1772
              strCmd+=String::SFormat(_T("%d"),m_pResource->Baud());
1773
              pc++;
1774
              continue;
1775
            case _TCHAR('p'):
1776
              if(_TCHAR('\0')==*(m_pResource->Serial())){
1777
                goto NextCmd; // Suppress output of this command if there is no serial port
1778
              }
1779
              strCmd+=m_pResource->Serial();
1780
              pc++;
1781
              continue;
1782
            case _TCHAR('\0'):
1783
              continue;
1784
            default:
1785
              break;
1786
          }
1787
          break;
1788
        default:
1789
          break;
1790
      }
1791
      strCmd+=*pc;
1792
    }
1793
    arstrInferiorCmds.push_back(strCmd);
1794
NextCmd:
1795
    ;
1796
  }
1797
  return;
1798
}
1799
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.