I am writing a job control shell. I use Yacc and Lex for parsing. The top rule in my grammar is pipeline_list, which is a list of pipelines separated by a comma. Thus, examples of pipelinelists are as follows:
cmd1 | cmd2; cmd3; cmd4 | cmd5 <newline>
cmd1 <newline>
<nothing> <newline>
I represent a pipeline with the pipeline rule (showed below). within that rule, I do the following:
1. call execute_pipeline() to execute the pipeline. execute_pipeline() returns -1 if anything went wrong in the execution of the pipeline.
2. Check the return value of execute_pipeline() and if it is -1, then STOP parsing the rest of the input, AND make sure YACC starts fresh when called again in the main function (shown below). The rationale for doing this is this:
Take, for example, the following pipelinelist: cd ..; ls -al. My intent here would be to move one directory up, and then list its content. However, if execution of the first pipeline (i.e., "cd ..") in the pipelinelist fails, then carrying on to execute the second pipeline (i.e. " ls -al") would list of the contents of the current directory (not the parent), which is wrong! For this reason, when parsing a pipelinelist of length n, if executing of some pipeline k > n fails, then I want to discard the rest of the pipelinelist (i.e., pipelines k+1..n), AND make sure the next invocation of yyparse() starts brand new (i.e. recieve new input from readline() -- see code below).
if tried the following, but it does not work:
pipeline:
simple_command_list redirection_list background pipeline_terminator // ignore these
{
if (execute_pipeline() == -1)
{
// do some stuff
// then call YYABORT, YYACCEPT, or YYERROR, but none of them works
}
}
int main()
{
while(1)
{
char *buffer = readline("> ");
if (buffer)
{
struct yy_buffer_state *bp;
bp = yy_scan_string(buffer);
yy_switch_to_buffer(bp);
yyparse()
yy_delete_buffer(bp);
free(buffer);
} // end if
} // end while
return 0;
} // end main()
You can use YYABORT; in an action to abort the current parse and immediately return from yyparse with a failure. You can use YYACCEPT; to immediately return success from yyparse.
Both of these macros can only be used directly in an action in the grammar -- they can't be used in some other function called by the action.
Related
I have declarative pipeline and uses jenkins shared library. I am trying to make recursive function call within jenkins shared library.
My shared lib structure is something similar to below :
vars/xyz.groovy
Inside xyz.groovy I have method foo, to whom I call xyz.foo from my pipeline which works.
However recursive call from
foo(){
foo() // says No such DSL method
xyz.foo() //says no signature of method: java.lang.class.foo
}
I am trying to understand how to calls functions within jenkins shared library.
this.methodName is rightway to call function recursively inside shared library. All though method is not a part of class. But using this.foo() worked for me.
I was trying something similar to invoke a recursive function with a method declared in the same file .groovy
At the end, the option #Sagar gave didn't work for me
As a workaround, I created the recursive function in a new file (b.groovy) and invoke it from the original file (a.groovy). it worked like a charm :)
example.
b.groovy
/**
* recursive function to compare semantic version form package.json and tag version, only evaluate x.x.x version
* 0 same version
* 1 package.json version is GREATER than repo tag version
* -1 package.json version is SMALLER than repo tag version
*/
int call(ArrayList versionPackageJsonSplit, ArrayList versionTagRepoSplit, Integer iteration) {
if (versionPackageJsonSplit[iteration].toInteger() == versionTagRepoSplit[iteration].toInteger()) {
if (iteration == 2) {
println 'return 0'
return 0
}
return utility_cdkCompareVersions (versionPackageJsonSplit, versionTagRepoSplit, iteration+1) // --> recursive invocation
} else if (versionPackageJsonSplit[iteration].toInteger() > versionTagRepoSplit[iteration].toInteger()) {
println 'return 1'
return 1
} else if (versionPackageJsonSplit[iteration].toInteger() < versionTagRepoSplit[iteration].toInteger()) {
println 'return -1'
return -1
}
}
a.groovy
.
.
.
compareVersionsResult = b (versionPackageJsonSplit, versionTagRepoSplit, 0)
println compareVersionsResult
.
.
.
.
```
So far the least awful way I've found to do this reliably is to create a top-level wrapper method with a recursive closure inside it:
def recursiveMethod(args) {
Closure rec
rec = { arg ->
if (recursiveCase) {
return rec(…)
}
else {
return baseCase
}
}
return rec(…)
}
The upside is that you can reference method args or method-scoped state variables from within the closure without having to pass them around the recursive stack, so recursive calls may look a little cleaner. The downside is a little extra boilerplate to do the wrapping, and also that the closure args have to be named differently than the method args or Groovy raises an error.
I cannot wrap my head around this PROMELA problem: I have N processes ("pc") which may both send and receive messages over a channel ("to_pc"). Each process has its own channel over which it receives messages.
For a process to be able to receive, I have to keep it in a loop which checks the channel for incoming messages. As a second loop option the process sends a message to all other channels.
However, in simulation mode, this always causes a timeout, without anything being sent at all. My theory so far is that I created a deadlock where all processes want to send at once, causing them all to be unable to receive (since they are stuck in their "send" part of the code).
So far I have been unable to resolve this problem. I have tried to use a global variable as a semaphore to "forbid" sending, so that only one channel may send. However, this did not change the results. My only other idea is to use a timeout as the trigger for the sending, but this does not seem right to me at all.
Any ideas? Thanks in advance!
#define N 4
mtype={request,reply}
typedef message {
mtype type;
byte target;
byte sender;
};
chan to_pc[N] = [0] of {message}
inline send() {
byte j = 0;
for (j : 0 .. N-1) {
if
:: j != address ->
to_pc[j]!msg;
:: else;
fi
}
}
active [N] proctype pc(){
byte address = _pid;
message msg;
do
:: to_pc[address]?msg -> /* Here I am receiving a message. */
if
::msg.type == request->
if
:: msg.target == address ->
d_step {
msg.target = msg.sender
msg.sender = address;
msg.type = reply;
}
send();
:: else
fi
:: msg.type == reply;
:: else;
fi
:: /* Here I want to send a message! */
d_step {
msg.target = (address + 1) % N;
msg.sender = address;
msg.type = request;
}
send();
od
};
I can write a full-fledged working version of your source code if you want, but perhaps it is sufficient to highlight the source of the issue you are dealing with and let you have fun solving it.
Branching Rules
any branch with an executable condition can be taken, non-deterministically
if there is no branch with an executable condition, the else branch is taken
if there is no branch with an executable condition and no else branch, then the process hangs till when one of the conditions becomes true
Consider this
1: if
2: :: in?stuff -> ...
3: :: out!stuff -> ...
4: fi
where in and out are both synchronous channels (size is 0).
Then
if someone is sending on the other end of in then in?stuff is executable, otherwise it is not
if someone is receiving on the other end of out then out!stuff is executable, otherwise it is not
the process blocks at line 1: up until when at least one of the two conditions is executable.
Compare that code to this
1: if
2: :: true -> in?stuff; ...
3: :: true -> out!stuff; ...
4: fi
where in and out are again synchronous channels (size is 0).
Then
both branches have an executable condition (true)
the process immediately commits itself to either send or receive something, by non-deterministically choosing to execute a branch either at line 2: or 3:
if the process chooses 2: then it blocks if in?stuff is not executable, even when out!stuff would be executable
if the process chooses 3: then it blocks if out!stuff is not executable, even when in!stuff would be executable
Your code falls in the latter situation, since all the instructions within d_step { } are executable and your process commits to send way too early.
To sum up: in order to fix your model, you should refactor your code so that it's always possible to jump from send to receive mode and viceversa. Hint: get rid of that inline code, separate the decision to send from actual sending.
2 Jenkins jobs: A and B.
A triggers B as blocking build step ("Block until the triggered projects finish their builds"). Is there a way to include B's console output into A's console output?
Motivation: for browser use of Jenkins A's console output contains a link to B's console output which is fine. But when using Jenkins via command line tools (jenkins-cli) there's no quick and easy way to see B's console output.
Any ideas?
Interesting. I'd try something like this.
From http://jenkinsurl/job/jobname/lastBuild/api/
Accessing Progressive Console Output
You can retrieve in-progress console output by making repeated GET requests with a parameter. You'll basically send GET request to this URL (or this URL if you want HTML that can be put into tag.) The start parameter controls the byte offset of where you start.
The response will contain a chunk of the console output, as well as the X-Text-Size header that represents the bytes offset (of the raw log file). This is the number you want to use as the start parameter for the next call.
If the response also contains the X-More-Data: true header, the server is indicating that the build is in progress, and you need to repeat the request after some delay. The Jenkins UI waits 5 seconds before making the next call. When this header is not present, you know that you've retrieved all the data and the build is complete.
So you can trigger a downstream job, but don't "block until downstream completes". Instead, add an extra step (execute shell, probably) and write a script that will read the console output of the other job as indicated above, and display it in console output of current job. You will have to detect when the child job finished by looking for X-More-Data: true header, as detailed above.
I know this is an old question, but i had to this myself recently. I figure this would help someone else looking to do the same. Here's a Groovy script that will read a given job's progressiveText URL. The code is written in such a way that it should be plug and play. Make sure to set the jenkinsBase and jobName first. The approach is no different to what has already been mentioned.
Here's a short set of instructions on how to use this: (1) Configure downstream job so that anonymous users hasRead and ViewStatus rights. (2) In the upstream job, create a Trigger/call builds on other projects step that will call the downstream job. (3) Do not check the "Block until the triggered projects finish their builds. (4) Right after that step, create an Execute Groovy script step and paste the following code:
def jenkinsBase = // Set to Jenkins base URL here
def jobName = // Set to jenkins job name
def jobNumber = 'lastBuild' // Tail last build
def address = null
def response = null
def start = 0 // Start at offset 0
def cont = true // This semaphore holds the value of X-More-Data header value
try {
while (cont == true) { // Loop while X-More-Data value is equal to true
address = "${jenkinsBase}/job/${jobName}/${jobNumber}/logText/progressiveText?start=${start}"
def urlInfo = address.toURL()
response = urlInfo.openConnection()
if (response.getResponseCode() != 200) {
throw new Exception("Unable to connect to " + address) // Throw an exception to get out of loop if response is anything but 200
}
if (start != response.getHeaderField('X-Text-Size')) { // Print content if the starting offset is not equal the value of X-Text-Size header
response.getInputStream().getText().eachLine { line ->
println(line)
}
}
start = response.getHeaderField('X-Text-Size') // Set new start offset to next byte
cont = response.getHeaderField('X-More-Data') // Set semaphore to value of X-More-Data field. If this is anything but true, we will fall out of while loop
sleep(3000) // wait for 3 seconds
}
}
catch (Exception ex) {
println (ex.getMessage())
}
This script can be further improved by programatically getting the downstream job number.
There is also a Python version of this approach here.
I want to exit execution of Lua script on some condition .
Example :
content = get_content()
if not content then
-- ( Here i want some kind of exit function )
next_content = get_content()
--example there can lot of further checks
Here I want that if I am not getting content my script suppose to terminate is should not go to check to next.
Use os.exit() or just return from some "main" function if your script is embedded.
os.exit()
kill process by sending a signal
do return end
stop execution
The two methods are not equal if you want to write and execute some luacode in the interpreter after stopping the execution by launching your program using the -i flag.
th -i main.lua
extract from the lua api doc :
For syntactic reasons, a break or return can appear only as the last statement of a block (in other words, as the last statement in your chunk or just before an end, an else, or an until). For instance, in the next example, break is the last statement of the then block.
local i = 1
while a[i] do
if a[i] == v then break end
i = i + 1
end
Usually, these are the places where we use these statements, because any other statement following them is unreachable. Sometimes, however, it may be useful to write a return (or a break) in the middle of a block; for instance, if you are debugging a function and want to avoid its execution. In such cases, you can use an explicit do block around the statement:
function foo ()
return --<< SYNTAX ERROR
-- `return' is the last statement in the next block
do return end -- OK
... -- statements not reached
end
In lua 5.2.0-beta-rc1+, you can add a label at the end of your code called ::exit:: or something of the like, and then whenever you need to exit the program just call it like this:
goto exit
The test below attempts to run the less pager command and return once
the user quits. The problem is that it doesn't wait for user input, it
just lists the entire file and exits. Platform: xubuntu 12.04, Dart
Editor build: 13049.
import 'dart:io';
void main() {
shell('less', ['/etc/mime.types'], (exitCode) => exit(exitCode));
}
void shell(String cmd, List<String> opts, void onExit(int exitCode)) {
var p = Process.start(cmd, opts);
p.stdout.pipe(stdout); // Process output to stdout.
stdin.pipe(p.stdin); // stdin to process input.
p.onExit = (exitCode) {
p.close();
onExit(exitCode);
};
}
The following CoffeeScript function (using nodejs I/O) works:
shell = (cmd, opts, callback) ->
process.stdin.pause()
child = spawn cmd, opts, customFds: [0, 1, 2]
child.on 'exit', (code) ->
process.stdin.resume()
callback code
How can I make this work in Dart?
John has a good example about how to look at user input. But doesn't answer your original question. Unfortunately your question doesn't fit with how Dart operates. The two examples you have, the Dart version and CoffeeScript/Node.js version, do two completely different things.
In your CoffeeScript version, the spawn command is actually creating a new process and then passing execution over to that new process. Basically you're program is not interactively communicating with the process, rather your user is interacting with the spawned process.
In Dart it is different, your program is interacting with the spawned process. It is not passing off execution to the new process. Basically what you are doing is piping the input/output to and from the new process to your program itself. Since your program doesn't have a 'window height' from the terminal, it passes all the information at once. What you're doing in dart is almost equivalent to:
less /etc/mime.types | cat
You can use Process.start() to interactively communicate with processes. But it is your program which is interactively communicating with the process, not the user. Thus you can write a dart program which will launch and automatically play 'zork' or 'adventure' for instance, or log into a remote server by looking at the prompts from process's output.
However, at current there is no way to simply pass execution to the spawned process. If you want to communicate the process output to a user, and then also take user input and send it back to a process it involves an additional layer. And even then, not all programs (such as less) behave the same as they do when launched from a shell environment.
Here's a basic structure for reading console input from the user. This example reads lines of text from the user, and exits on 'q':
import 'dart:io';
import 'dart:isolate';
final StringInputStream textStream = new StringInputStream(stdin);
void main() {
textStream.onLine = checkBuffer;
}
void checkBuffer(){
final line = textStream.readLine();
if (line == null) return;
if (line.trim().toLowerCase() == 'q'){
exit(0);
}
print('You wrote "$line". Now write something else!');
}