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 33

Details | Compare with Previous | View Log

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