|
Post by bigbass on May 29, 2013 15:23:13 GMT 1
Well this is something that I wanted to do but was very complex to mentally sort out because of low level memory C and high level memory BaCon basic
because of the mixture of pointers,structures,arrays,and BaCon RECORD
combined with knowing nothing solid about any of these before starting to convert code to PROTO I wanted to document some of the steps
what can be done
Able now to get C structures three ways 1.) HARDWARE_CODE = (event->hardware_keycode) PRINT "event hardware_keycode as a variable ", HARDWARE_CODE
2.)PRINT "event hardware_keycode directly using print ",(event->hardware_keycode)
3.)PRINT "roseta stone of getting a structure! ", event[0].hardware_keycode
and it gets even better! I was able to place these in a BaCon RECORD
RECORD UGLY_C_STRUCTURE LOCAL x LOCAL y END RECORD
WITH UGLY_C_STRUCTURE .y = event[0].keyval END WITH
here is the code I will break it down in several posts later and update any progress
PRAGMA LDFLAGS `pkg-config --libs gtk+-2.0` PRAGMA OPTIONS `pkg-config --cflags gtk+-2.0` PRAGMA INCLUDE <gtk-2.0/gtk/gtk.h> PRAGMA INCLUDE <gtk-2.0/gdk/gdk.h>
'--- GTK PROTO gtk_init PROTO gtk_main PROTO gtk_widget_show PROTO gtk_window_new PROTO gtk_exit PROTO gtk_window_set_title
'---extras PROTO g_signal_connect_data
'--- GDK PROTO gdk_keyval_name PROTO gdk_keyval_to_unicode
'--- Declare variables DECLARE *window TYPE GtkWidget
'========================================================= FUNCTION key_event(GtkWidget *widget, GdkEventKey *event) '========================================================= LOCAL keypressed LOCAL $keypressed LOCAL SPECIAL_KEYS keypressed = gdk_keyval_to_unicode(event->keyval) $keypressed = gdk_keyval_name(event->keyval) SPECIAL_KEYS = gdk_unicode_to_keyval(event->keyval) PRINT "KEYPRESSED = ", $keypressed ," UNICODE VALUE= ",keypressed ," SPECIAL KEY= " ,SPECIAL_KEYS HARDWARE_CODE = (event->hardware_keycode) PRINT "event hardware_keycode as a variable ", HARDWARE_CODE PRINT "event hardware_keycode directly using print ",(event->hardware_keycode) ' roseta stone of getting a structure! PRINT "roseta stone of getting a structure! ", event[0].hardware_keycode PRINT "roseta stone of getting a structure time ! ", event[0].time PRINT "roseta stone of getting a structure keyval ! ", event[0].keyval PRINT "event time ",(event->time) '================place a real C structure in a BaCon RECORD============= 'lets do some something special take a read only memory STRUCTURE 'and simulate read write memory on a layer in BaCon RECORD UGLY_C_STRUCTURE LOCAL x LOCAL y END RECORD
WITH UGLY_C_STRUCTURE .x = event[0].time .y = event[0].keyval END WITH
PRINT PRINT "the low level memory idea is but this syntax doesnt work this way in BACON" PRINT PRINT "x = ", "UGLY_C_STRUCTURE[0].x"
PRINT PRINT "but in BaCon we use RECORD and WITH using high level memory" PRINT "using this syntax UGLY_C_STRUCTURE.x" PRINT PRINT "UGLY_C_STRUCTURE->x " , "can NOW be translated to" PRINT "UGLY_C_STRUCTURE.x " PRINT "the value is = " ,UGLY_C_STRUCTURE.x
gtk_window_set_title(GTK_WINDOW(window), $keypressed ) RETURN FALSE
END FUNCTION
'--- Callback for closing window '================================ SUB exit_prog '================================ PRINT "QUIT" gtk_exit(0) END SUB
gtk_init (0, 0)
window = gtk_window_new (GTK_WINDOW_TOPLEVEL) gtk_window_set_title(GTK_WINDOW(window), "get key press")
'--- Use as callback the defined SUB/FUNCTIONS g_signal_connect_data(window, "delete-event", exit_prog, 0, 0, 0) g_signal_connect_data(window, "key-release-event", G_CALLBACK(key_event) ,0, 0, 0)
gtk_widget_show (window) gtk_main
|
|
|
Post by bigbass on May 29, 2013 16:04:25 GMT 1
you get the STUCTURE info from here /usr/include/gtk-2.0/gdk/gdkevents.h More info about what each does is here developer.gnome.org/gdk3/stable/gdk3-Event-Structures.html#GdkEventKeythen look for this part struct _ GdkEventKey{ GdkEventType type; GdkWindow *window; gint8 send_event; guint32 time; guint state; guint keyval; gint length; gchar *string; guint16 hardware_keycode; guint8 group; guint is_modifier : 1; }; we will use time, keyval and hardware_keycode for the demo we have to make a FUNCTION to get at this info note you have to ignore the leading underscore '--- Declare variables DECLARE *window TYPE GtkWidget DECLARE *event TYPE GdkEventKey'========================================================= FUNCTION key_event(GtkWidget *widget, GdkEventKey *event) '========================================================= we need a callback for the FUNCTION g_signal_connect_data(window, "key-release-event", G_CALLBACK( key_event) ,0, 0, 0)
|
|
|
Post by bigbass on May 30, 2013 15:45:14 GMT 1
Some may prefer a HUG look to the code and that is fine so why not I like the idea of using * include for just the sake of quickly knowing this file is an INCLUDE file
Well, this is a way to "simulate" the shorthand commands made famous by HUG without having to actually include HUG.bac with this example in the end this is just another optional way to test prototype code using BaCon
can that be done using just PROTO ? yes, and it is easy to customize to whatever commands you want to see and use the idea is old simply have a readable spoken type language when possible
*in other examples casting could be removed also it is noisy in the terminal just to show what is happening so you could modify it easily to your needs
there is still a lot that can be done with STRUCTS I just wanted to simplify the code example first
lets face it using GTK or embedding it is ugly but with a bit of make up we can take her to the party
Press any key and the value shows in the GUI and in the terminal more detailed info is shown
compile the same standard way as usual
key.bac
INCLUDE "getkey.bac"
START(0, 0)
window = WINDOW(GTK_WINDOW_TOPLEVEL) TITLE(GTK_WINDOW(window), "get key press")
'--- Use as callback the defined SUB/FUNCTIONS CALLBACK(window, "delete-event", exit_prog, 0, 0, 0) CALLBACK(window, "key-release-event", G_CALLBACK(key_event) ,0, 0, 0)
SHOW(window) DISPLAY
getkey.bac this is the include file for the backend to communicate with the low level GTK GDK code
PRAGMA LDFLAGS `pkg-config --libs gtk+-2.0` PRAGMA OPTIONS `pkg-config --cflags gtk+-2.0` PRAGMA INCLUDE <gtk-2.0/gtk/gtk.h> PRAGMA INCLUDE <gtk-2.0/gdk/gdk.h>
'--- GTK PROTO gtk_init ALIAS START PROTO gtk_main ALIAS DISPLAY PROTO gtk_widget_show ALIAS SHOW PROTO gtk_window_new ALIAS WINDOW PROTO gtk_exit PROTO gtk_window_set_title ALIAS TITLE
'---extras PROTO g_signal_connect_data ALIAS CALLBACK
'--- GDK PROTO gdk_keyval_name ALIAS GET_NAME PROTO gdk_keyval_to_unicode ALIAS GET_UINCODE
'--- Declare variables DECLARE *window TYPE GtkWidget
'========================================================= FUNCTION key_event(GtkWidget *widget, GdkEventKey *event) '========================================================= LOCAL keypressed LOCAL $keypressed LOCAL SPECIAL_KEYS
keypressed = gdk_keyval_to_unicode(event->keyval) $keypressed = GET_NAME(event->keyval) SPECIAL_KEYS = GET_UINCODE(event->keyval)
PRINT "KEYPRESSED = ", $keypressed ," UNICODE VALUE= ",keypressed ," SPECIAL KEY= " ,SPECIAL_KEYS
HARDWARE_CODE = (event->hardware_keycode) PRINT "event hardware_keycode as a variable ", HARDWARE_CODE PRINT "event hardware_keycode directly using print ",(event->hardware_keycode) ' roseta stone of getting a structure! PRINT "roseta stone of getting a structure! ", event[0].hardware_keycode PRINT "roseta stone of getting a structure time ! ", event[0].time PRINT "roseta stone of getting a structure keyval ! ", event[0].keyval PRINT "event time ",(event->time) '================place a real C structure in a BaCon RECORD============= 'lets do some something special take a read only memory STRUCTURE 'and simulate read write memory on a layer in BaCon RECORD UGLY_C_STRUCTURE LOCAL x LOCAL y END RECORD
WITH UGLY_C_STRUCTURE .x = event[0].time .y = event[0].keyval END WITH
PRINT PRINT "the low level memory idea is but this syntax doesnt work this way in BACON" PRINT PRINT "x = ", "UGLY_C_STRUCTURE[0].x"
PRINT PRINT "but in BaCon we use RECORD and WITH using high level memory" PRINT "using this syntax UGLY_C_STRUCTURE.x" PRINT PRINT "UGLY_C_STRUCTURE->x " , "can NOW be translated to" PRINT "UGLY_C_STRUCTURE.x " PRINT "the value is = " ,UGLY_C_STRUCTURE.x
TITLE(GTK_WINDOW(window), $keypressed )
RETURN FALSE
END FUNCTION
'--- Callback for closing window '================================ SUB exit_prog '================================ PRINT "QUIT" gtk_exit(0) END SUB
tested code again to compile correctly in 2019
|
|
|
Post by vovchik on Jun 1, 2013 16:04:10 GMT 1
Dear Joe,
I missed this post. Very valuable, so my thanks.
With kind regards, vovchik
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on Jun 1, 2013 18:18:41 GMT 1
Most languages and APIs are over weight with a ton of junk in the trunk.
Repeat after me ...
Memory is cheap and what'is a few extra seconds matter anyways?
|
|
|
Post by bigbass on Jun 11, 2013 16:38:47 GMT 1
Recently barry.k wrote a kernel-uevents in BaCon sourceforge.net/p/baconproto/wiki/kernel-uevents/ (in my above examples it was done differently I used GDK /GTK pointers then stored the members in a RECORD later) since this is a complex low level example in just C I will explain how the struct was converted to BaCon using RECORD directly which is a different approach Link to the header used www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/asm/poll.h?v=2.6.11.8fixed old links code.woboq.org/qt5/include/bits/poll.h.htmlconvert the defines to decimal later ================================= #define POLLIN 0x0001================================= 'C code defines PORTED to BaCON CONST POLLIN = 1
======================= struct pollfd { int fd; short events; short revents; }; ======================== now convert this into a RECORD '--- struct pollfd, defined in asm-generic/poll.h... RECORD pfd LOCAL fd TYPE int LOCAL events TYPE short LOCAL revents TYPE short END RECORD
Toggle line number - Style: /* Copyright (C) 1997-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ #ifndef _SYS_POLL_H # error "Never use <bits/poll.h> directly; include <sys/poll.h> instead." #endif /* Event types that can be polled for. These bits may be set in `events' to indicate the interesting event types; they will appear in `revents' to indicate the status of the file descriptor. */ #define POLLIN 0x001 /* There is data to read. */ #define POLLPRI 0x002 /* There is urgent data to read. */ #define POLLOUT 0x004 /* Writing now will not block. */ #if defined __USE_XOPEN || defined __USE_XOPEN2K8 /* These values are defined in XPG4.2. */ # define POLLRDNORM 0x040 /* Normal data may be read. */ # define POLLRDBAND 0x080 /* Priority data may be read. */ # define POLLWRNORM 0x100 /* Writing now will not block. */ # define POLLWRBAND 0x200 /* Priority data may be written. */ #endif #ifdef __USE_GNU /* These are extensions for Linux. */ # define POLLMSG 0x400 # define POLLREMOVE 0x1000 # define POLLRDHUP 0x2000 #endif /* Event types always implicitly polled for. These bits need not be set in `events', but they will appear in `revents' to indicate the status of the file descriptor. */ #define POLLERR 0x008 /* Error condition. */ #define POLLHUP 0x010 /* Hung up. */ #define POLLNVAL 0x020 /* Invalid polling request. */
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on Jun 11, 2013 20:42:17 GMT 1
FYI
If you DECLARE the structure in BaCon you can reference it in BASIC code like in C with . notation.
|
|
|
Post by bigbass on Jun 12, 2013 17:10:20 GMT 1
|
|
|
Post by bigbass on Jun 13, 2013 5:30:31 GMT 1
I kept searching for the source code and this most likely is it www.kernel.org/doc/pending/hotplug.txthaving the original then the BaConized code shows us how to port more code into BaCon it serves as an educational tool and since this thread is dedicated to structures it is a fine example what to do to get struct and RECORD working together now adding GTK or GTK to the backend will be easier Here's a C program to print hotplug netlink events to stdout: #include <stdio.h> #include <stdlib.h> #include <string.h>
#include <sys/poll.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h>
#include <linux/types.h> #include <linux/netlink.h>
void die(char *s) { write(2,s,strlen(s)); exit(1); }
int main(int argc, char *argv[]) { struct sockaddr_nl nls; struct pollfd pfd; char buf[512];
// Open hotplug event netlink socket
memset(&nls,0,sizeof(struct sockaddr_nl)); nls.nl_family = AF_NETLINK; nls.nl_pid = getpid(); nls.nl_groups = -1;
pfd.events = POLLIN; pfd.fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); if (pfd.fd==-1) die("Not root\n");
// Listen to netlink socket
if (bind(pfd.fd, (void *)&nls, sizeof(struct sockaddr_nl))) die("Bind failed\n"); while (-1!=poll(&pfd, 1, -1)) { int i, len = recv(pfd.fd, buf, sizeof(buf), MSG_DONTWAIT); if (len == -1) die("recv\n");
// Print the data to stdout. i = 0; while (i<len) { printf("%s\n", buf+i); i += strlen(buf+i)+1; } } die("poll\n");
// Dear gcc: shut up. return 0; }
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on Jun 14, 2013 5:36:57 GMT 1
|
|
|
Post by bigbass on Jun 17, 2013 16:04:15 GMT 1
This breaks down the wall of importing structs! ;D
The goal here is to be able to port some complex C code structures and embed them in BaCon for the end goal of having a way to make use of tens of thousands of code snippets that use struct
since struct is used so often in C porting struct code to BaCon is now easy
there is no documented information about porting struct to BaCon with example code this is the main focus of the topic
and example code will be shown and explained with two simple getting started examples and one real word use of making a struct then storing values in a struct in several different ways getting info from the system
struct-int-proto.bac simple interger struct
'--- now it is possible to use structs with PROTO ! '--- record is the name of the struct in this example '--- note that the secret here is to enclose the struct name like this (record) '--- looks simple but this took several days to get it to work
PROTO struct PROTO printf
'--- use a struct declare an interger member struct { int age; } (record) ; record.age = 20 ;
printf("age is %d\n", record.age)
struct-char-proto.bac simple character struct
'--- now it is possible to use structs with PROTO ! '--- record is the name of the struct in this example '--- note that the secret here is to enclose the struct name like this (record) '--- looks simple but this took several days to get it to work
PROTO struct PROTO printf
'--- use a struct declare a string member struct { char * name; } (record) ; record.name = "Joe" ;
printf("name is %s\n", record.name)
struct-proto-demo.bac make a struct using PROTO then fill the members
'--- using C stucts in BaCon! '--- undocumented tricks '--- by bigbass June 13 2013
PROTO struct PROTO printf
'--- use a struct declare string members '--- show how to get around BaCon strings having the ending $ '--- when C stuctures wont allow the ending $ '--- ugly because lines need to be escaped but one long line is worse
struct { \ char * release ; \ char * libc ; \ char * version; \ char * gtk2version; \ char * gtk3version; \ char * gooversion; \ char * machine; \ char * kernel; ; \ char * extra;} (stuff) ;
'--- Current BaCon release result$ = EXEC$(CONCAT$("bacon -v" )) stuff.release = result$ '--- Current glibc version result2$ = EXEC$(CONCAT$("/lib/libc.so.6 | head -1" )) stuff.libc = result2$ '--- Current bash version result3$ = EXEC$(CONCAT$("echo $BASH_VERSION" )) stuff.version = result3$
'--- Current gtk2 version result4$ = EXEC$(CONCAT$("cat /usr/lib/pkgconfig/gtk+-2.0.pc |grep Version:" )) stuff.gtk2version = result4$
'--- Current gtk3 version result5$ = EXEC$(CONCAT$("cat /usr/lib/pkgconfig/gtk+-3.0.pc |grep Version:")) stuff.gtk3version = result5$
'--- Current goocanvas version result6$ = EXEC$(CONCAT$("cat /usr/lib/pkgconfig/goocanvas.pc |grep Version:" )) stuff.gooversion = result6$ '--- hardware type the system is running on. result7$ = EXEC$(CONCAT$("uname -p" )) stuff.machine = result7$
'--- kernel the system is running on. result8$ = EXEC$(CONCAT$("uname -r" )) stuff.kernel = result8$
'--- HUG version depends on the correct path to file result9$ = EXEC$(CONCAT$("cat /usr/share/BaCon/hug.bac|grep Version |tail -1| cut -d '-' -f1" )) stuff.extra = result9$
printf ("\n") printf ("==============================================\n") printf ("System info gathered then placed in a struct \n") printf ("============================================== \n")
printf ("%s", stuff.release) printf ("GLIBC = %s", stuff.libc) printf ("BASH VERSION = %s", stuff.version) printf ("GTK2 = %s", stuff.gtk2version) printf ("GTK3 = %s", stuff.gtk3version) printf ("GOOCANVAS = %s", stuff.gooversion) printf ("HARDWARE = %s", stuff.machine) printf ("KERNEL = %s", stuff.kernel) printf ("HUG = %s\n", stuff.extra)
|
|
|
Post by vovchik on Jun 17, 2013 16:41:14 GMT 1
Dear Joe,
YIPPEE and HOORAY! Many thanks - and your explanation is very clear. This will make a lot of stuff much easier to use. Great work.
With kind regards, vovchik
|
|
|
Post by bigbass on Jun 22, 2013 6:23:13 GMT 1
@structs and BaCon ! well ... it can be done and it is done and no offsets to calculate and no need for RECORD a complete working test example of PROTO struct '--- How to PROTO a struct define it and use it by bigbass
DECLARE i TYPE int DECLARE ch TYPE char DECLARE d TYPE double DECLARE str TYPE char ARRAY 80
PROTO printf,scanf,struct
struct struct_type { int i; char ch; double d; char str[80];} (s);
printf("Enter an integer: "); scanf("%d:", &s.i);
printf("Enter a character: "); scanf(" %c", &s.ch);
printf("Enter a floating point number: "); scanf("%lf", &s.d);
printf("Enter a string: "); scanf("%s", s.str);
printf("\n"); printf("interger: %d\n", s.i); printf("character: %c\n", s.ch); printf("floating point number: %f\n", s.d); printf("string: %s\n", s.str);
|
|
|
Post by Pjot on Jun 22, 2013 8:21:42 GMT 1
Thanks bigbass, Like this we don't need the USEC statement anymore...? BR, Peter
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on Jun 22, 2013 8:55:22 GMT 1
FYIIf you DECLARE the structure in BaCon you can reference it in BASIC code like in C with . notation. Looks like Joe took the hint.
|
|