Выполнение сценария TCL из строки N - PullRequest
0 голосов
/ 30 мая 2019

У меня есть сценарий TCL, который говорит, имеет 30 строк кода автоматизации, которые я выполняю в оболочке dc (Synopsys Design Compiler). Я хочу остановить и выйти из сценария в строке 10, выйти из оболочки dc и вернуть ее снова после выполнения ручного просмотра. Однако на этот раз я хочу запустить скрипт, начиная со строки № 11, без необходимости выполнять первые 10 строк.

Вместо двух сценариев, один из которых содержит код до строки № 10, а другой - с другим, я хотел бы использовать только один сценарий и попытаться выполнить его, скажем, со строки № N.

Что-то вроде: source a.tcl -line 11

Как я могу это сделать?

Ответы [ 2 ]

1 голос
/ 31 мая 2019

Если у вас Tcl 8.6+ и вы планируете перемоделировать свой скрипт поверх сопрограммы Tcl , вы можете реализовать это поведение продолжения в несколько строк.Это предполагает, что вы запускаете скрипт из интерактивной оболочки Tcl (dc shell?).

# script.tcl
if {[info procs allSteps] eq ""} {
    # We are not re-entering (continuing), so start all over.
    proc allSteps {args} {
      yield; # do not run when defining the coroutine;
      puts 1
      puts 2
      puts 3
      yield; # step out, once first sequence of steps (1-10) has been executed
      puts 4
      puts 5
      puts 6
      rename allSteps ""; # self-clean, once the remainder of steps (11-N) have run
    }
    coroutine nextSteps allSteps
}

nextSteps; # run coroutine
  1. Упакуйте ваш скрипт в тело процедуры (allSteps).
  2. В пределахтело процедуры: поместите yield, чтобы указать точку удержания / продолжения после ваших первых шагов (например, после 10-го шага).
  3. Создайте сопрограмму nextSteps на основе allSteps.
  4. Защитите определения proc и coroutine таким образом, чтобы они не вызывали повторное определение (когда выполняются шаги)

Затем запустите интерактивную оболочку и выполните source script.tcl:

% source script.tcl
1
2
3

Теперь выполните ручную проверку.Затем продолжите в той же оболочке:

% source script.tcl
4
5
6

Обратите внимание, что вы можете запускать общую двухфазную последовательность любое количество раз (из-за самоочищения процедуры сопрограммы: rename):

% source script.tcl
1
2
3
% source script.tcl
4
5
6

Еще раз: все это предполагает, что вы не выходите из оболочки и поддерживаете ее при выполнении обзора.Если вам необходимо выйти из оболочки по какой-либо причине (или вы не можете запустить Tcl 8.6+), то предложение Донала - это путь.

Обновление

Если применимо в вашем случае,Вы можете улучшить реализацию, используя анонимный (лямбда) proc .Это упрощает управление жизненным циклом (избегая переопределения, управления сопрограммами и процессами, нет необходимости в rename):

# script.tcl
if {[info commands nextSteps] eq ""} {
    # We are not re-entering (continuing), so start all over.
    coroutine nextSteps apply {args {
      yield; # do not run when defining the coroutine;
      puts 1
      puts 2
      puts 3
      yield; # step out, once first sequence of steps (1-10) has been executed
      puts 4
      puts 5
      puts 6
    }}
}

nextSteps
0 голосов
/ 30 мая 2019

Самый простой способ - открыть текстовый файл, разобрать его, чтобы получить первые N команды (там полезно info complete), а затем оценить их (или остальную часть сценария).При этом эффективно получается немного другой код, когда вы отбрасываете хвост, в отличие от того, когда вы отбрасываете префикс.

proc ReadAllLines {filename} {
    set f [open $filename]
    set lines {}
    # A little bit careful in case you're working with very large scripts
    while {[gets $f line] >= 0} {
        lappend lines $line
    }
    close $f
    return $lines
}

proc SourceFirstN {filename n} {
    set lines [ReadAllLines $filename]
    set i 0
    set script {}
    foreach line $lines {
        append script $line "\n"
        if {[info complete $script] && [incr i] >= $n} {
            break              
        }
    }
    info script $filename
    unset lines
    uplevel 1 $script
}

proc SourceTailN {filename n} {
    set lines [ReadAllLines $filename]
    set i 0
    set script {}
    for {set j 0} {$j < [llength $lines]} {incr j} {
        set line [lindex $lines $j]
        append script $line "\n"
        if {[info complete $script]} {
            if {[incr i] >= $n} {
                info script $filename
                set realScript [join [lrange $lines [incr j] end] "\n"]
                unset lines script
                return [uplevel 1 $realScript]
            }
            # Dump the prefix we don't need any more
            set script {}
        }
    }
    # If we get here, the script had fewer than n lines so there's nothing to do
}

Имейте в виду, что типы файлов, с которыми вы имеете дело, могут стать довольно большимии Tcl в настоящее время имеет некоторые жесткие ограничения памяти.С другой стороны, если вы вообще можете source файл, вы уже в пределах этого лимита ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...