Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 9287 - Implement -stdin. #6880

Merged
merged 2 commits into from
Aug 1, 2017
Merged

Issue 9287 - Implement -stdin. #6880

merged 2 commits into from
Aug 1, 2017

Conversation

quickfur
Copy link
Member

@quickfur quickfur commented Jun 9, 2017

It's nice to be able to pipe source code into dmd via standard input, e.g., in code generation programs so that you don't have to create a temporary file just to be able to compile the code.

Based on the bug notes in the original bug, using - to mean stdin is probably a problematic idea, so I have chosen a different route, i.e., use -stdin to indicate that dmd should read source code from stdin. I think this is clearer, and less *nix-specific.

@quickfur
Copy link
Member Author

quickfur commented Jun 9, 2017

Note that I had to hack together a stdio-based way of copying data from stdin into a buffer, because the existing File class in src/ddmd/root/file.d does not work with non-file handles: it uses stat to discover the total file length, which is not available with stdin. I also opted for using stdio so that I don't have to figure out how to write a Windows-specific version which I currently have no way to test.

@quickfur quickfur force-pushed the stdin branch 3 times, most recently from 85d13f5 to 34d8d78 Compare June 9, 2017 22:47
src/ddmd/mars.d Outdated
size_t pos = 0;
size_t sz = bufIncrement;

ubyte* buf = cast(ubyte*).malloc(sz + 1); // +1 for sentinel
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

malloc is only meant for buffers which are freed later.
use xmalloc amd xrealloc instead
even better would be in walking the length of the input and the using allocmemory.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went with xmalloc / xrealloc. Didn't really want to walk the input, since it could be large, if xrealloc already takes care of allocating a large-enough buffer for us.

@UplinkCoder
Copy link
Member

@quickfur what is the specific usecase for this ?

@wilzbach
Copy link
Member

wilzbach commented Jun 9, 2017

@quickfur if you use "Fix " as a commit message, the bot will recognize it (more infos).

@UplinkCoder most tools/compilers allow this - this is nice for a bunch of use cases starting with showing compile errors in my favorite editor (most editors read the un-saved instance in-memory and thus can nicely pipe it to dmd) - see the issue for more details.

@quickfur
Copy link
Member Author

Also, please advise if there is a better place to put copyFile than directly in mars.d. Somehow it feels a little out-of-place there.

@WalterBright
Copy link
Member

Protocol: when creating a PR to fix Issue https://issues.dlang.org/show_bug.cgi?id=9287, add a link in bugzilla to the PR. I already did so for this.

@WalterBright
Copy link
Member

As I commented in https://issues.dlang.org/show_bug.cgi?id=9287 please use - not -stdin. We shouldn't be reinventing common Linux conventions.

@wilzbach
Copy link
Member

12.82% of diff hit (target 85.504%)
85.461% (-0.044%) compared to ebd995a

Sorry to bother you with this, but adding a test in the testsuite for this will highly increase chances of acceptance ;-)

@quickfur
Copy link
Member Author

@WalterBright I did put the PR link in bugzilla, did you miss it?

As for '-' instead of '-stdin', I'll get to it later. Thanks for the feedback.

PS: where's the best place to put 'copyFile'?

@quickfur
Copy link
Member Author

@wilzbach How would you test something involving standard input? I don't know if the current test suite runner is capable of piping code via stdin.

@wilzbach
Copy link
Member

@wilzbach How would you test something involving standard input? I don't know if the current test suite runner is capable of piping code via stdin.

The test suite is Turing-complete (it allows the use of Bash), see e.g. this simple test:

#!/usr/bin/env bash

src=runnable${SEP}extra-files
dir=${RESULTS_DIR}${SEP}runnable
output_file=${dir}/test10567.sh.out

$DMD -m${MODEL} -I${src} -of${dir}${SEP}test10567a${OBJ} -c ${src}${SEP}test10567a.d || exit 1
$DMD -m${MODEL} -I${src} -of${dir}${SEP}test10567${EXE} ${src}${SEP}test10567.d ${dir}${SEP}test10567a${OBJ} || exit 1
${RESULTS_DIR}/runnable/test10567${EXE} || exit 1

rm ${dir}/{test10567a${OBJ},test10567${EXE}}

echo Success >${output_file}

Simply rewriting sth. like this to use cat should work ;-)
You can run an individual test with make test_results/<name of test>.out

@quickfur
Copy link
Member Author

Thanks for the tip! Got a working test now.

@quickfur
Copy link
Member Author

Hmm, the Jenkins errors appear unrelated to the changes in this PR. What's going on?

@quickfur
Copy link
Member Author

Nevermind, it seems to be affecting other PRs too.

src/ddmd/mars.d Outdated
size_t sz = bufIncrement;

ubyte* buf = cast(ubyte*)mem.xmalloc(sz + 1); // +1 for sentinel
if (buf is null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

xmalloc() never returns null

src/ddmd/mars.d Outdated
assert(sz > pos);
size_t rlen;
pos += rlen = fread(buf + pos, 1, sz - pos, fp);
while (!ferror(fp) && !feof(fp))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This loop can be written so there is only one xmalloc call instead of two, and one fread instead of two.

src/ddmd/mars.d Outdated
{
if (pos == sz)
{
sz += bufIncrement;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reallocating every 4K bytes makes for a very slow read. expression.d is 500K, so that makes for 125 copies and reallocations. I'd probably make it at least 128K.

src/ddmd/mars.d Outdated
assert(sz > pos);
pos += rlen = fread(buf + pos, 1, sz - pos, fp);
}
if (ferror(fp))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ferror is checking twice

src/ddmd/mars.d Outdated
/**
* Copies data from a FILE* into a newly-allocated buffer.
*
* The buffer is always null-terminated.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Ddoc style comments, with Params: and Returns: sections.

src/ddmd/mars.d Outdated
@@ -1210,6 +1260,10 @@ Language changes listed by -transition=id:
{
files.push(cast(char*)global.main_d); // a dummy name, we never actually look up this file
}
if (global.params.readStdin)
{
files.push(cast(char*)global.stdin_d); // a dummy name, we don't actually look it up
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe put this before line 1134, then the test doesn't have to be done twice

src/ddmd/mars.d Outdated
@@ -1343,6 +1397,22 @@ Language changes listed by -transition=id:
}
}
}
if (global.params.readStdin)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this code should go into root/file.d, as reading from stdin should be a low level thing, not a high level one.

@WalterBright
Copy link
Member

I suggest that if root.File.read() simply checked for "-" as a filename in File.name, the logic could all be moved there and the the rest of the complicated logic can be removed from the main code.

@andralex
Copy link
Member

great review (and idea) @WalterBright

@dlang-bot
Copy link
Contributor

Thanks for your pull request, @quickfur!

Bugzilla references

Auto-close Bugzilla Description
9287 DMD should read from stdin when an input file is "-"

@quickfur
Copy link
Member Author

Ah, he's expecting the word "issue". Got it, thanks!

@wilzbach
Copy link
Member

Ah, he's expecting the word "issue". Got it, thanks!

Exact regex-> https://github.com/dlang-bots/dlang-bot#nerdy-details
Though I don't know why the double posts happened - maybe yet another lag in the GH event API?

@quickfur
Copy link
Member Author

ping @WalterBright @andralex

Is this PR satisfactory, or should a different approach be taken? Please advise, thanks!

@andralex
Copy link
Member

It seems the PR cannot be made much simpler. I'm mildly in favor of the notion of accepting piped input, without being able to think of a solid application. OK with me. @WalterBright ?

src/ddmd/mars.d Outdated
@@ -1033,6 +1033,8 @@ Language changes listed by -transition=id:
goto Lnoarg;
}
}
else if (p[1] == '\0')
files.push("__stdin");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not pushing __stdin.d to avoid ambiguities?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, done.

@dlang-bot
Copy link
Contributor

Thanks for your pull request, @quickfur!

Bugzilla references

Auto-close Bugzilla Description
9287 DMD should read from stdin when an input file is "-"

@dlang-bot
Copy link
Contributor

Thanks for your pull request, @quickfur!

Bugzilla references

Auto-close Bugzilla Description
9287 DMD should read from stdin when an input file is "-"

@quickfur
Copy link
Member Author

Rebased, hopefully this fixes the travis error which seems unrelated.

@andralex What else needs to be done to get this PR merged?

@andralex
Copy link
Member

andralex commented Aug 1, 2017

@WalterBright 's call

@quickfur
Copy link
Member Author

quickfur commented Aug 1, 2017

@andralex I was referring to your change requested review. @WalterBright already approved this PR.

@wilzbach
Copy link
Member

wilzbach commented Feb 3, 2018

So why do we should we add verbose changelog entries?
(reminder for the future)

Mention passing files from stdin as potential use case
thanks Seb, didn't know that.
lindt/docker-dmd#5

Of course, it's in the changelog, but at the end and rather hard to spot:

image

https://dlang.org/changelog/2.076.0.html

@ibuclaw
Copy link
Member

ibuclaw commented Feb 3, 2018

Heh, I implemented this feature two months before this PR, and it seems to have the same __stdin name given to the input module.

D-Programming-GDC/gdc@dd81b9a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
10 participants