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

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.7/] [tools/] [src/] [librtcltools/] [RtclArgs.cpp] - Blame information for rev 19

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

Line No. Rev Author Line
1 19 wfjm
// $Id: RtclArgs.cpp 492 2013-02-24 22:14:47Z mueller $
2 10 wfjm
//
3 19 wfjm
// Copyright 2011-2013 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4 10 wfjm
//
5
// This program is free software; you may redistribute and/or modify it under
6
// the terms of the GNU General Public License as published by the Free
7
// Software Foundation, either version 2, or at your option any later version.
8
//
9
// This program is distributed in the hope that it will be useful, but
10
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
11
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
// for complete details.
13
// 
14
// Revision History: 
15
// Date         Rev Version  Comment
16 19 wfjm
// 2013-02-12   487   1.0.6  add CurrentArg() method
17
// 2013-02-03   481   1.0.5  use Rexception
18 10 wfjm
// 2011-03-26   373   1.0.4  add GetArg(float/double)
19
// 2011-03-13   369   1.0.3  add GetArg(vector<unit8_t>); NextOpt clear NOptMiss
20
// 2011-03-06   367   1.0.2  add Config() methods;
21
// 2011-03-05   366   1.0.1  fObjc,fNDone now size_t; add NDone(), SetResult();
22
//                           add GetArg(Tcl_Obj), PeekArgString();
23
// 2011-02-26   364   1.0    Initial version
24
// 2011-02-11   360   0.1    First draft
25
// ---------------------------------------------------------------------------
26
 
27
/*!
28
  \file
29 19 wfjm
  \version $Id: RtclArgs.cpp 492 2013-02-24 22:14:47Z mueller $
30 10 wfjm
  \brief   Implemenation of RtclArgs.
31
*/
32
 
33
//debug
34
#include <iostream>
35
 
36
#include <ctype.h>
37
#include <stdarg.h>
38
 
39 19 wfjm
#include "RtclArgs.hpp"
40 10 wfjm
 
41
#include "Rtcl.hpp"
42 19 wfjm
#include "librtools/Rexception.hpp"
43 10 wfjm
 
44
using namespace std;
45
 
46
/*!
47
  \class Retro::RtclArgs
48
  \brief FIXME_docs
49
*/
50
 
51 19 wfjm
// all method definitions in namespace Retro
52
namespace Retro {
53
 
54 10 wfjm
//------------------------------------------+-----------------------------------
55
//! Default constructor
56
 
57
RtclArgs::RtclArgs()
58
  : fpInterp(0),
59
    fObjc(0),
60
    fObjv(0),
61
    fNDone(0),
62
    fNOptMiss(0),
63
    fNConfigRead(0),
64
    fOptErr(false),
65
    fArgErr(false)
66
{}
67
 
68
//------------------------------------------+-----------------------------------
69
//! FIXME_docs
70
 
71
RtclArgs::RtclArgs(Tcl_Interp* interp, int objc, Tcl_Obj* const objv[],
72
                   size_t nskip)
73
  : fpInterp(interp),
74
    fObjc((size_t)objc),
75
    fObjv(objv),
76
    fNDone((nskip<=(size_t)objc) ? nskip : (size_t)objc),
77
    fNOptMiss(0),
78
    fNConfigRead(0),
79
    fOptErr(false),
80
    fArgErr(false)
81
{
82
  if (objc < 0)
83 19 wfjm
    throw Rexception("RtclArgs::<ctor>","Bad args: objc must be >= 0");
84 10 wfjm
}
85
 
86
//------------------------------------------+-----------------------------------
87
//! FIXME_docs
88
 
89
RtclArgs::RtclArgs(const RtclArgs& rhs)
90
  : fpInterp(rhs.fpInterp),
91
    fObjc(rhs.fObjc),
92
    fObjv(rhs.fObjv),
93
    fNDone(rhs.fNDone),
94
    fNOptMiss(rhs.fNOptMiss),
95
    fOptErr(rhs.fOptErr),
96
    fArgErr(rhs.fArgErr)
97
{}
98
 
99
//------------------------------------------+-----------------------------------
100
//! Destructor
101
 
102
RtclArgs::~RtclArgs()
103
{}
104
 
105
//------------------------------------------+-----------------------------------
106
//! FIXME_docs
107
 
108
Tcl_Obj* RtclArgs::Objv(size_t ind) const
109
{
110
  if (ind >= (size_t)fObjc)
111 19 wfjm
    throw Rexception("RtclArgs::Objv()","Bad args: index out-of-range");
112 10 wfjm
  return fObjv[ind];
113
}
114
 
115
//------------------------------------------+-----------------------------------
116
//! FIXME_docs
117
 
118
bool RtclArgs::GetArg(const char* name, Tcl_Obj*& pval)
119
{
120
  Tcl_Obj* pobj;
121
  if (!NextArg(name, pobj)) return false;
122
  if (pobj==0) return true;
123
  pval = pobj;
124
  return true;
125
}
126
 
127
//------------------------------------------+-----------------------------------
128
//! FIXME_docs
129
 
130
bool RtclArgs::GetArg(const char* name, const char*& val)
131
{
132
  Tcl_Obj* pobj;
133
  if (!NextArg(name, pobj)) return false;
134
  if (pobj==0) return true;
135
  val = Tcl_GetString(pobj);
136
  return true;
137
}
138
 
139
//------------------------------------------+-----------------------------------
140
//! FIXME_docs
141
 
142
bool RtclArgs::GetArg(const char* name, std::string& val)
143
{
144
  Tcl_Obj* pobj;
145
  if (!NextArg(name, pobj)) return false;
146
  if (pobj==0) return true;
147
  val = Tcl_GetString(pobj);
148
  return true;
149
}
150
 
151
//------------------------------------------+-----------------------------------
152
//! FIXME_docs
153
 
154
bool RtclArgs::GetArg(const char* name, int8_t& val, int8_t min, int8_t max)
155
{
156
  int32_t val32 = (int32_t)val;
157
  bool ret = GetArg(name, val32, (int32_t)min, (int32_t)max);
158
  val = (int8_t) val32;
159
  return ret;
160
}
161
 
162
//------------------------------------------+-----------------------------------
163
//! FIXME_docs
164
 
165
bool RtclArgs::GetArg(const char* name, uint8_t& val, uint8_t max, uint8_t min)
166
{
167
  uint32_t val32 = (uint32_t)val;
168
  bool ret = GetArg(name, val32, (uint32_t)max, (uint32_t)min);
169
  val = (uint8_t) val32;
170
  return ret;
171
}
172
 
173
//------------------------------------------+-----------------------------------
174
//! FIXME_docs
175
 
176
bool RtclArgs::GetArg(const char* name, int16_t& val, int16_t min, int16_t max)
177
{
178
  int32_t val32 = (int32_t)val;
179
  bool ret = GetArg(name, val32, (int32_t)min, (int32_t)max);
180
  val = (int16_t) val32;
181
  return ret;
182
}
183
 
184
//------------------------------------------+-----------------------------------
185
//! FIXME_docs
186
 
187
bool RtclArgs::GetArg(const char* name, uint16_t& val, uint16_t max,
188
                      uint16_t min)
189
{
190
  uint32_t val32 = (uint32_t)val;
191
  bool ret = GetArg(name, val32, (uint32_t)max, (uint32_t)min);
192
  val = (uint16_t) val32;
193
  return ret;
194
}
195
 
196
//------------------------------------------+-----------------------------------
197
//! FIXME_docs
198
 
199
bool RtclArgs::GetArg(const char* name, int32_t& val, int32_t min, int32_t max)
200
{
201
  Tcl_Obj* pobj;
202
  if (!NextArg(name, pobj)) return false;
203
  if (pobj==0) return true;
204
  int objval;
205
  if (Tcl_GetIntFromObj(fpInterp, pobj, &objval) != TCL_OK) return false;
206
  if (objval < min || objval > max) {
207
    ostringstream sos;
208
    sos << "-E: value '" << objval << "' for '" << name << "' out of range "
209
        << min << "..." << max;
210
    AppendResult(sos);
211
    return false;
212
  }
213
  val = (int32_t) objval;
214
  return true;
215
}
216
 
217
//------------------------------------------+-----------------------------------
218
//! FIXME_docs
219
 
220
bool RtclArgs::GetArg(const char* name, uint32_t& val, uint32_t max,
221
                      uint32_t min)
222
{
223
  Tcl_Obj* pobj;
224
  if (!NextArg(name, pobj)) return false;
225
  if (pobj==0) return true;
226
  int objval;
227
  if (Tcl_GetIntFromObj(fpInterp, pobj, &objval) != TCL_OK) return false;
228
  unsigned int objuval = objval;
229
  if (objuval < min || objuval > max) {
230
    ostringstream sos;
231
    sos << "-E: value '" << objuval << "' for '" << name << "' out of range "
232
        << min << "..." << max;
233
    AppendResult(sos);
234
    return false;
235
  }
236
  val = (uint32_t) objval;
237
  return true;
238
}
239
 
240
//------------------------------------------+-----------------------------------
241
//! FIXME_docs
242
 
243
bool RtclArgs::GetArg(const char* name, float& val, float min, float max)
244
{
245
  double vald = (double)val;
246
  bool ret = GetArg(name, vald, (double)max, (double)min);
247
  val = (float) vald;
248
  return ret;
249
}
250
 
251
//------------------------------------------+-----------------------------------
252
//! FIXME_docs
253
 
254
bool RtclArgs::GetArg(const char* name, double& val, double min, double max)
255
{
256
  Tcl_Obj* pobj;
257
  if (!NextArg(name, pobj)) return false;
258
  if (pobj==0) return true;
259
  double objval;
260
  if (Tcl_GetDoubleFromObj(fpInterp, pobj, &objval) != TCL_OK) return false;
261
  if (objval < min || objval > max) {
262
    ostringstream sos;
263
    sos << "-E: value '" << objval << "' for '" << name << "' out of range "
264
        << min << "..." << max;
265
    AppendResult(sos);
266
    return false;
267
  }
268
  val = objval;
269
  return true;
270
}
271
 
272
//------------------------------------------+-----------------------------------
273
//! FIXME_docs
274
 
275
bool RtclArgs::GetArg(const char* name, std::vector<uint8_t>& val,
276
                      size_t lmin, size_t lmax)
277
{
278
  int objc = 0;
279
  Tcl_Obj** objv = 0;
280
  if (!NextArgList(name, objc, objv, lmin, lmax)) return false;
281
  if (objv==0) return true;
282
 
283
  val.clear();
284
  val.reserve(objc);
285
 
286
  for (int i=0; i<objc; i++) {
287
    int ival;
288
    if (Tcl_GetIntFromObj(fpInterp, objv[i], &ival) != TCL_OK) return false;
289
    int ivalmsb = ival>>8;
290
    if (ivalmsb != 0 && ivalmsb != -1) {
291
      ostringstream sos;
292
      sos << "-E: list element '" << Tcl_GetString(objv[i])
293
          << "' for '" << name
294
          << "' out of range " << "0...0xff";
295
      AppendResult(sos);
296
      return false;
297
    }
298
    val.push_back((uint8_t)ival);
299
  }
300
  return true;
301
}
302
 
303
//------------------------------------------+-----------------------------------
304
//! FIXME_docs
305
 
306
bool RtclArgs::GetArg(const char* name, std::vector<uint16_t>& val,
307
                      size_t lmin, size_t lmax)
308
{
309
  int objc = 0;
310
  Tcl_Obj** objv = 0;
311
  if (!NextArgList(name, objc, objv, lmin, lmax)) return false;
312
  if (objv==0) return true;
313
 
314
  val.clear();
315
  val.reserve(objc);
316
 
317
  for (int i=0; i<objc; i++) {
318
    int ival;
319
    if (Tcl_GetIntFromObj(fpInterp, objv[i], &ival) != TCL_OK) return false;
320
    int ivalmsb = ival>>16;
321
    if (ivalmsb != 0 && ivalmsb != -1) {
322
      ostringstream sos;
323
      sos << "-E: list element '" << Tcl_GetString(objv[i])
324
          << "' for '" << name
325
          << "' out of range " << "0...0xffff";
326
      AppendResult(sos);
327
      return false;
328
    }
329
    val.push_back((uint16_t)ival);
330
  }
331
  return true;
332
}
333
 
334
//------------------------------------------+-----------------------------------
335
//! FIXME_docs
336
 
337
bool RtclArgs::Config(const char* name, std::string& val)
338
{
339
  ConfigNameCheck(name);
340
  string tmp = val;
341
  if (!GetArg(name, tmp)) return false;
342
  if (fNOptMiss == 0) {                     // config write
343
    val = tmp;
344
  } else {                                  // config read
345
    if (!ConfigReadCheck()) return false;
346
    SetResult(Tcl_NewStringObj(val.data(), val.length()));
347
  }
348
  return true;
349
}
350
 
351
//------------------------------------------+-----------------------------------
352
//! FIXME_docs
353
 
354
bool RtclArgs::Config(const char* name, uint32_t& val, uint32_t max,
355
                      uint32_t min)
356
{
357
  ConfigNameCheck(name);
358
  uint32_t tmp = val;
359
  if (!GetArg(name, tmp, max, min)) return false;
360
  if (fNOptMiss == 0) {                     // config write
361
    val = tmp;
362
  } else {                                  // config read
363
    if (!ConfigReadCheck()) return false;
364
    SetResult(Tcl_NewIntObj((int)val));
365
  }
366
  return true;
367
}
368
 
369
//------------------------------------------+-----------------------------------
370
//! FIXME_docs
371
 
372
bool RtclArgs::NextOpt(std::string& val)
373
{
374
  fNOptMiss = 0;
375
  val.clear();
376
  fOptErr = false;
377
 
378
  if (fNDone == fObjc) return false;
379
 
380
  const char* str = PeekArgString(0);
381
 
382
  if (str[0]=='-' && str[1] && !isdigit(str[1])) {
383
    fNDone += 1;
384
    // '--' seen (eat it, and say no Opt's found)
385
    if (str[1]=='-' && str[2]==0) {
386
      return false;
387
    }
388
    val = str;
389
    return true;
390
  }
391
  return false;
392
}
393
 
394
//------------------------------------------+-----------------------------------
395
//! FIXME_docs
396
 
397
bool RtclArgs::NextOpt(std::string& val, RtclNameSet& optset)
398
{
399
  val.clear();
400
  string opt;
401
  if (!NextOpt(opt) || opt.empty()) return false;
402
 
403
  fOptErr = !optset.Check(fpInterp, val, opt);
404
  return !fOptErr;
405
}
406
 
407
//------------------------------------------+-----------------------------------
408
//! FIXME_docs
409
 
410 19 wfjm
Tcl_Obj* RtclArgs::CurrentArg() const
411
{
412
  if (fNDone == 0)
413
    throw Rexception("RtclArgs::CurrentArg()",
414
                     "Bad state: no argument processed yet");
415
 
416
  return fObjv[fNDone-1];
417
}
418
 
419
//------------------------------------------+-----------------------------------
420
//! FIXME_docs
421
 
422 10 wfjm
bool RtclArgs::AllDone()
423
{
424
  if (fArgErr || fOptErr) return false;
425
  if (fNDone < fObjc) {
426 19 wfjm
    AppendResult("-E: superfluous arguments, first one '",
427
                 Tcl_GetString(fObjv[fNDone]), "'", NULL);
428 10 wfjm
    return false;
429
  }
430
  return true;
431
}
432
 
433
//------------------------------------------+-----------------------------------
434
//! FIXME_docs
435
 
436
const char* RtclArgs::PeekArgString(int rind) const
437
{
438
  int ind = fNDone + rind;
439
  if (ind < 0 || ind >= (int)fObjc) return "";
440
  return Tcl_GetString(fObjv[ind]);
441
}
442
 
443
//------------------------------------------+-----------------------------------
444
//! FIXME_docs
445
 
446
void RtclArgs::AppendResult(const char* str, ...)
447
{
448
  Tcl_AppendResult(fpInterp, str, NULL);
449
  va_list ap;
450
  va_start (ap, str);
451
  Tcl_AppendResultVA(fpInterp, ap);
452
  va_end (ap);
453
  return;
454
}
455
 
456
//------------------------------------------+-----------------------------------
457
//! FIXME_docs
458
 
459
void RtclArgs::AppendResultLines(const std::string& str)
460
{
461
  Rtcl::AppendResultNewLines(fpInterp);
462
 
463
  if (str.length()>0 && str[str.length()-1]=='\n') {
464
    Tcl_AppendResult(fpInterp, str.substr(0,str.length()-1).c_str(), NULL);
465
  } else {
466
    Tcl_AppendResult(fpInterp, str.c_str(), NULL);
467
  }
468
  return;
469
}
470
 
471
//------------------------------------------+-----------------------------------
472
//! FIXME_docs
473
 
474
bool RtclArgs::NextArg(const char* name, Tcl_Obj*& pobj)
475
{
476
  pobj = 0;
477
 
478
  bool isopt    = name[0] == '?';
479
  bool isoptopt = isopt && (name[1] == '?');
480
 
481
  if (!isopt) fNOptMiss = 0;
482
 
483
  if (fNDone == fObjc) {
484
    if (!isopt) {
485 19 wfjm
      AppendResult("-E: required argument '", name, "' missing", NULL);
486 10 wfjm
      fArgErr = true;
487
      return false;
488
    }
489
    fNOptMiss += 1;
490
    return true;
491
  }
492
 
493
  // if %% arg peek in next arg and check that it's not an option
494
  if (isoptopt) {
495
    const char* nval = Tcl_GetString(fObjv[fNDone]);
496
    if (nval[0]=='-' && nval[1] && isalpha(nval[1])) {
497
      fNOptMiss += 1;
498
      return true;
499
    }
500
  }
501
 
502
  pobj = fObjv[fNDone++];
503
 
504
  return true;
505
}
506
 
507
//------------------------------------------+-----------------------------------
508
//! FIXME_docs
509
 
510
bool RtclArgs::NextArgList(const char* name, int& objc, Tcl_Obj**& objv,
511
                           size_t lmin, size_t lmax)
512
{
513
  objc = 0;
514
  objv = 0;
515
  Tcl_Obj* pobj = 0;
516
  if (!NextArg(name, pobj)) return false;
517
  if (pobj==0) return true;
518
 
519
  if (Tcl_ListObjGetElements(fpInterp, pobj, &objc, &objv) != TCL_OK) {
520
    return false;
521
  }
522
 
523
  if ((size_t)objc < lmin || (size_t)objc > lmax) {
524
    ostringstream sos;
525
    sos << "-E: list length '" << objc << "' for '" << name << "' out of range "
526
        << lmin << "..." << lmax;
527
    AppendResult(sos);
528
    return false;
529
  }
530
  return true;
531
}
532
 
533
//------------------------------------------+-----------------------------------
534
//! FIXME_docs
535
 
536
void RtclArgs::ConfigNameCheck(const char* name)
537
{
538
  if (name==0 || name[0]!='?' || name[1]!='?')
539 19 wfjm
    throw Rexception("RtclArgs::Config()","Bad args: name must start with ??");
540 10 wfjm
  return;
541
}
542
 
543
//------------------------------------------+-----------------------------------
544
//! FIXME_docs
545
 
546
bool RtclArgs::ConfigReadCheck()
547
{
548
  if (fNConfigRead != 0) {
549
    SetResult(Tcl_NewObj());
550 19 wfjm
    AppendResult("-E: only one config read allowed per command, '",
551
                 PeekArgString(-1), "' is second", NULL);
552 10 wfjm
    return false;
553
  }
554
  fNConfigRead += 1;
555
  return true;
556
}
557
 
558 19 wfjm
} // end namespace Retro

powered by: WebSVN 2.1.0

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