How to effectively insert into string?

2020-03-09 Thread Jan Synacek
Hello,

how do I write a function that inserts into a string (or deletes from a
string) effectively in guile? There's some mention about how strings are
implemented in the info manual, but it's not really clear to me. Is it
necessary to implement a gap buffer / rope / something similar, or can it
effectively be achieved with only guile's strings?

I also have a related question. Let's say I have a spec file (as in the one
used by RPM) and I need to add several lines to the section of patches
which looks like this:

...
Patch0001: ...
Patch0002: ...
Patch0003: ...
...

That is, I'd like to process the file and add "Patch0004...\nPatch0005..."
after the Patch0003 line, then save the file. What is the best way to do
this in guile? Is it better to read the entire file and then use something
like regexp-substitute or is there a better way?

Thank you,
-- 
Jan Synacek
Software Engineer, Red Hat


Incomplete backtrace

2020-03-11 Thread Jan Synacek
Hello,

consider the following piece of code:

$ cat test.scm
(use-modules (ice-9 regex))

(define (change text)
  (regexp-substitute #f (string-match "string" text)
'pre
"something" 0
'post))

(define (main)
  (change "there will be no match"))

(main)

When I run the script, I get a backtrace:

$ guile -s test.scm
Backtrace:
In ice-9/boot-9.scm:
  1736:10  8 (with-exception-handler _ _ #:unwind? _ # _)
In unknown file:
   7 (apply-smob/0 #)
In ice-9/boot-9.scm:
718:2  6 (call-with-prompt _ _ #)
In ice-9/eval.scm:
619:8  5 (_ #(#(#)))
In ice-9/boot-9.scm:
   2806:4  4 (save-module-excursion _)
  4351:12  3 (_)
In ice-9/ports.scm:
550:4  2 (call-with-output-string _)
In ice-9/boot-9.scm:
   260:13  1 (for-each # …)
In ice-9/regex.scm:
 64:2  0 (_ _)

Why do I not see the exact place where the problem is? Why are there
underscores instead? Why do I not even see that the error originated in
test.scm? I can't find any explanation about this in the manual.

While this code was extracted from a bigger program and it's obvious where
the problem is, it was super hard to figure it out in the original program.
Because the backtrace actually doesn't even point in the right place, it's
quite useless in my opinion.

Am I doing anything wrong? I use guile 3.0.1.

Regards,
-- 
Jan Synacek
Software Engineer, Red Hat


Re: Incomplete backtrace

2020-03-11 Thread Jan Synacek
On Wed, Mar 11, 2020 at 7:07 PM Jan Synacek  wrote:

> Hello,
>
> consider the following piece of code:
>
> $ cat test.scm
> (use-modules (ice-9 regex))
>
> (define (change text)
>   (regexp-substitute #f (string-match "string" text)
> 'pre
> "something" 0
> 'post))
>
> (define (main)
>   (change "there will be no match"))
>
> (main)
>
> When I run the script, I get a backtrace:
>
> $ guile -s test.scm
> Backtrace:
> In ice-9/boot-9.scm:
>   1736:10  8 (with-exception-handler _ _ #:unwind? _ # _)
> In unknown file:
>7 (apply-smob/0 #)
> In ice-9/boot-9.scm:
> 718:2  6 (call-with-prompt _ _ #)
> In ice-9/eval.scm:
> 619:8  5 (_ #(#(#)))
> In ice-9/boot-9.scm:
>2806:4  4 (save-module-excursion _)
>   4351:12  3 (_)
> In ice-9/ports.scm:
> 550:4  2 (call-with-output-string _)
> In ice-9/boot-9.scm:
>260:13  1 (for-each # …)
> In ice-9/regex.scm:
>  64:2  0 (_ _)
>

I forgot one line in the backtrace output:

ice-9/regex.scm:64:2: In procedure vector-ref: Wrong type argument in
position 1 (expecting vector): #f

Which sort of gives a hint, but not really...

-- 
Jan Synacek
Software Engineer, Red Hat


FFI questions

2020-05-15 Thread Jan Synacek
Hello,

Currently I have something like this:

(define libxcb (dynamic-link "libxcb"))

...

(define c-change-window-attributes
  (pointer->procedure void
 (dynamic-func "xcb_change_window_attributes" libxcb)
 (list '* uint32 uint32 '*)))

(define (change-window-attributes conn win mask vals)
   (c-change-window-attributes conn win mask (bytevector->pointer vals)))

The last argument to xcb_change_window_attributes is 'const void *' and I
need to pass a u32 vector to it. As it is right now, it segfaults when I
try passing #u32(something) to 'change-window-attributes'. Is it possible
to make it accept a u32 vector using just Scheme or do I have to work
around it on the C level?


My second question is about FFI and structs. Is it possible to access C
struct members from Scheme by name? If not, how do I generally approach the
problem? I've checked how guile-xcb does it and it seems to be building
hash tables with field names as keys. But that basically requires me to
"redefine" all the C structs that I would be interested in at the Scheme
level.

Regards,
-- 
Jan Synacek
Software Engineer, Red Hat


Re: FFI questions

2020-05-17 Thread Jan Synacek
On Fri, May 15, 2020 at 10:09 PM Taylan Kammer  wrote:
>
> On 15.05.2020 15:47, Jan Synacek wrote:
> > Hello,
> >
> > Currently I have something like this:
> >
> > (define libxcb (dynamic-link "libxcb"))
> >
> > ...
> >
> > (define c-change-window-attributes
> >(pointer->procedure void
> >   (dynamic-func "xcb_change_window_attributes" libxcb)
> >   (list '* uint32 uint32 '*)))
> >
> > (define (change-window-attributes conn win mask vals)
> > (c-change-window-attributes conn win mask (bytevector->pointer vals)))
> >
> > The last argument to xcb_change_window_attributes is 'const void *' and I
> > need to pass a u32 vector to it. As it is right now, it segfaults when I
> > try passing #u32(something) to 'change-window-attributes'. Is it possible
> > to make it accept a u32 vector using just Scheme or do I have to work
> > around it on the C level?
>
> I think the reason it segfaults might be that the #u32() object gets
> garbage collected soon after you call bytevector->pointer on it.  See
> that you put it in a variable, and reference that variable at some point
> after xcb_change_windor_attributes should be done with the vector, to
> make sure that this is not the problem.
>
> Otherwise I'm not sure why it should segfault.  A #u32() bytevector
> really should be backed by a contiguous array of uint32_t values, just
> like what you'll get when you define a uint32_t[] in C.

This works, thanks!

(define (change-window-attributes conn win mask vals)
  (define b (list->u32vector vals))
  (c-xcb-change-window-attributes conn win mask (bytevector->pointer b)))

> > My second question is about FFI and structs. Is it possible to access C
> > struct members from Scheme by name? If not, how do I generally approach the
> > problem? I've checked how guile-xcb does it and it seems to be building
> > hash tables with field names as keys. But that basically requires me to
> > "redefine" all the C structs that I would be interested in at the Scheme
> > level.
>
> These might be useful:
>
> https://github.com/TaylanUB/scheme-bytestructures
>
> https://www.nongnu.org/nyacc/ffi-help.html
>
> I maintain bytestructures, am happy to answer questions.  (If I don't
> respond on the mailing list, feel free to mail me directly or open an
> issue on GitHub; mails with guile-user@gnu.org and guile-de...@gnu.org
> in the To: or Cc: fields land in a folder that I don't always check.)

Very interesting, I'll take a look.

Thank you,
-- 
Jan Synacek
Software Engineer, Red Hat