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

Subversion Repositories w11

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

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

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