|
Post by bigbass on Jun 22, 2013 22:36:59 GMT 1
for me there is no better way to understand (and remember) than seeing some working code example the easier the better so here is a C program struct source as a reference ported to BaCon below You will notice how I combined the library with the struct code and a nice example of gets some may complain so I also did an example with fgets below source code www.9wy.net/onlinebook/CPrimerPlus5/ch14lev1sec1.html#ch14list01BaConized struct code '-- book.c -- one-book inventory ported to BaCon by bigbass
CONST MAXTITL = 41 CONST MAXAUTL = 31
PROTO struct PROTO printf,gets,scanf
DECLARE title TYPE char ARRAY 41 DECLARE author TYPE char ARRAY 31
struct book { char title[MAXTITL]; char author[MAXAUTL]; float value;}(library)
printf("Please enter the book title.\n"); gets(library.title); printf("Now enter the author.\n"); gets(library.author); printf("Now enter the value.\n"); scanf("%f", &library.value); printf("%s by %s: $%.2f\n",library.title, library.author, library.value); printf("Done.\n");
fgets version
'-- book.c -- one-book inventory ported to BaCon by bigbass '--- updated with fgets note fgets adds the enter key to the input
CONST MAXTITL = 41 CONST MAXAUTL = 31
PROTO struct PROTO printf,fgets,scanf
DECLARE title TYPE char ARRAY 41 DECLARE author TYPE char ARRAY 31
struct book { char title[MAXTITL]; char author[MAXAUTL]; float value;}(library)
printf("Please enter the book title.\n"); fgets(library.title, 41, stdin); printf("Now enter the author.\n"); fgets(library.author,31,stdin); printf("Now enter the value.\n"); scanf("%f", &library.value); printf("\n"); printf(" TITLE : %s ",library.title); printf("AUTHOR : %s ",library.author); printf("COST : $%.2f", library.value); printf("\n");
|
|
|
Post by bigbass on Jul 16, 2013 17:49:34 GMT 1
some more practice with structs
removing the need to DECLARE thus shortening code
original C code
#include <stdio.h> struct programming { float constant; char *pointer; }; main() { struct programming variable; char string[] = "Programming in Software Development."; variable.constant = 1.23; variable.pointer = string; printf("%f\n", variable.constant); printf("%s\n", variable.pointer); return 0; }
bacon ported code pointer doesnt need to be a pointer anymore in bacon
PROTO struct PROTO printf '--- use a struct declare floating point member and a string member struct programming { double constant; char * pointer; } (variable) ; variable.constant = 1.23 variable.pointer = "Programming in Software Development." printf("%f\n", variable.constant); printf("%s\n", variable.pointer);
|
|
|
Post by bigbass on Jul 26, 2013 16:54:34 GMT 1
We can finally get any info from low level structs!!this is a major break though I had tried to solve this many, many times before so this is like winning a trophy for me We are now able to read the low level header structs and print the data in BaCon This is an advanced topic but shows some new untapped power of what BaCon can do and look no need for USEC /END USEC kernel-ver.bac '---Joe Arose aka..bigbass finally solved using structs reading '---the low level sys headers directly and getting the data July 25 2013 '---example with printf and BaCons PRINT to see the differences
PRAGMA INCLUDE <sys/utsname.h>
'--- import C functions used PROTO printf PROTO struct PROTO uname
struct utsname (u) uname (&u) printf ("%s kernel %s (version %s) on %s\n", u.sysname, u.release, u.version, u.machine) PRINT u.sysname, u.release, u.version, u.machine FORMAT "%s kernel %s (version %s) on %s\n"
./kernel-ver Linux kernel 3.2.29-smp (version #2 SMP Mon Sep 17 13:16:43 CDT 2012) on i686 Linux kernel 3.2.29-smp (version #2 SMP Mon Sep 17 13:16:43 CDT 2012) on i686
|
|
|
Post by vovchik on Jul 26, 2013 18:25:35 GMT 1
Dear Joe,
That is fabulous work. Thanks.
With kind regards, Vovchik
|
|
|
Post by bigbass on Feb 19, 2014 20:47:41 GMT 1
Now with porting even more code from C for external libraries
structure can be difficult to port so having several examples will make it easier
this is plain C first then we will see the BaCon version ported
#include <glib.h>
struct test_struct { gint32 gint32_member1; gchar gchar_member2; gint8 gint8_member3; };
int main(int argc, char *argv[]) { struct test_struct *tsptr, ts; ts.gint32_member1 = 32; ts.gchar_member2 = 's'; ts.gint8_member3 = 8;
tsptr = &ts;
g_printf("ts.gint32_member1: %d\n", G_STRUCT_MEMBER(gint32, tsptr, 0)); g_printf("ts.gchar_member2: %c\n", G_STRUCT_MEMBER(gchar, tsptr, 4)); g_printf("ts.gint8_member3: %d\n", G_STRUCT_MEMBER(gint8, tsptr, 5));
return 0; }
PRAGMA INCLUDE glib-2.0/glib.h PRAGMA OPTIONS -I /usr/include/glib-2.0/ PRAGMA OPTIONS -I /usr/lib/i386-linux-gnu/glib-2.0/include/
PROTO printf PROTO struct
struct { gint32 gint32_member1; gchar gchar_member2; gint8 gint8_member3; } (ts )
ts.gint32_member1 = 32 ts.gchar_member2 = 's' ts.gint8_member3 = 8
printf("ts.gint32_member1: %d\n", G_STRUCT_MEMBER(gint32, &ts, 0)); printf("ts.gchar_member2: %c\n", G_STRUCT_MEMBER(gchar, &ts, 4)); printf("ts.gint8_member3: %d\n", G_STRUCT_MEMBER(gint8, &ts, 5));
|
|
|
Post by bigbass on Feb 20, 2014 16:17:03 GMT 1
Converting structs to BaCon in steps look at the prior post to see that we went from an UGLY hardware struct using glib and embedded it in BaCon (not fun but it can be done when needed)
now we go one step more and convert it to use BaCon's RECORD command I will comment more what is happening in the next post
this macro will become useful for us G_STRUCT_MEMBER just trying to get it into BaCon cleanly
I shortened the code a little not using pointers or the struct alias just using the struct name "ts" directly Joe
PRAGMA INCLUDE glib-2.0/glib.h PRAGMA OPTIONS -I /usr/include/glib-2.0/ PRAGMA OPTIONS -I /usr/lib/i386-linux-gnu/glib-2.0/include/
'--- import functions PROTO printf
'--- name the struct "ts" and decalare it '--- with the TYPEs that will be used RECORD ts LOCAL gint32_member1 TYPE gint32 LOCAL gchar_member2 TYPE gchar LOCAL gint8_member3 TYPE gint8 END RECORD
ts.gint32_member1 = 32 ts.gchar_member2 = 's' ts.gint8_member3 = 8
printf("ts.gint32_member1: %d\n", G_STRUCT_MEMBER(gint32, &ts, 0)) printf("ts.gchar_member2: %c\n", G_STRUCT_MEMBER(gchar, &ts, 4)) printf("ts.gint8_member3: %d\n", G_STRUCT_MEMBER(gint8, &ts, 5))
|
|
|
Post by vovchik on Feb 20, 2014 17:08:47 GMT 1
Dear Joe,
It's a nice example. Thanks.
With kind regards, vovchik
|
|
|
Post by bigbass on Jun 25, 2014 17:40:08 GMT 1
kernel-uevents Connect a USB and get real time info from it I will only focus on the documentation of the port Before I start forum member barryk did an excellent port of kernel-ueventsit only lacked a link to the original source code used however he overcame some difficult problems with the structs when porting the code to bacon which was a very important step that I feel needs to be documented this is really a complex code example because it uses low level structs Thank you barryk for the hard work you did on this to get the code to compile and run ! *I just want to document this based on some C source code for educational reasons For the documentation we will base everything off this source code to port to BaCon www.kernel.org/doc/pending/hotplug.txt landley.net/kdocs/pending/hotplug.txtsince I don't know exactly what code was used before and this looks like a good example I reused a lot of code from barryk to make this documentation part possible basic-converter.proboards.com/thread/502RECORD pfd converted from struct pollfd pfd; basic-converter.proboards.com/post/4279 Joe just compile the code the connect or disconnect a usb to see the information in the terminal hotplug3.bac
'--- from linux/netlink.h CONST NETLINK_KOBJECT_UEVENT = 15
'--- linux/poll.h, only includes asm/poll.h, which only includes asm-generic/poll.h CONST POLLIN = 1
'--- C functions PROTO them to make them available in BaCon PROTO getpid, socket, bind, poll, recv, printf,write,memset,exit
'--- defined in linux/netlink.h '--- struct sockaddr_nl nls; RECORD nls LOCAL nl_family TYPE unsigned short LOCAL nl_pad TYPE unsigned short LOCAL nl_pid TYPE unsigned int LOCAL nl_groups TYPE unsigned int END RECORD
'--- defined in asm-generic/poll.h '--- struct pollfd pfd; RECORD pfd LOCAL fd TYPE int LOCAL events TYPE short LOCAL revents TYPE short END RECORD
DECLARE buf[512] TYPE char
'================ SUB SEND_OUT() '================ PRINT "poll" PRINT "Use ctrl+c to break and quit " END SUB
'--- Open hotplug event netlink socket memset(&nls,0,SIZEOF(nls)) 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) THEN PRINT "***No permission or no root***" SEND_OUT END IF
'--- Listen to netlink socket IF (bind(pfd.fd, (void *)&nls, SIZEOF(nls))) THEN PRINT "***Bind failed***" SEND_OUT END IF
PRINT "Connect or disconnect something to the USB port" WHILE (-1!=poll(&pfd, 1, -1))
i = 0 len = recv(pfd.fd, buf, SIZEOF(buf), MSG_DONTWAIT) IF (len == -1) THEN PRINT "recv" SEND_OUT END IF '--- Print the data to stdout. i = 0 WHILE (i<len) printf("%s\n", buf+i) i = i + strlen(buf+i)+1 WEND SEND_OUT
WEND
|
|
|
Post by bigbass on Jun 26, 2014 17:41:47 GMT 1
Now the detailed explination I will append more info to this post Produce header free code of those C code headers only a few constants ,enums and structs are needed 1.) remove the #include <sys/poll.h> www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/asm/poll.h?v=2.6.11.8The first step convert the hex value to decimal #define POLLIN 0x0001 In BaCon CONST POLLIN = 1 2.) convert the C struct to a RECORD this has a typedef pfd struct pollfd { int fd; short events; short revents; }; '--- struct pollfd pfd; RECORD pfd LOCAL fd TYPE int LOCAL events TYPE short LOCAL revents TYPE short END RECORD
---------------------------------------------------------------------- 3.)Remove the netlink.h by supplying only what is needed from the header dyxa.com/code.php?file=linux/netlink.hWe will have to convert this struct struct sockaddr_nl { sa_family_t nl_family; /* AF_NETLINK */ unsigned short nl_pad; /* zero */ __u32 nl_pid; /* process pid */ __u32 nl_groups; /* multicast groups mask */ };
In BaCon we use the typedef nls '--- struct sockaddr_nl nls; RECORD nls LOCAL nl_family TYPE unsigned short LOCAL nl_pad TYPE unsigned short LOCAL nl_pid TYPE unsigned int LOCAL nl_groups TYPE unsigned int END RECORD
4.) convert the #define to a BaCon CONST #define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */ In BaCon this is '--- from linux/netlink.h CONST NETLINK_KOBJECT_UEVENT = 15 ----------------------------------------------------------------------
|
|
|
Post by bigbass on Jun 30, 2014 15:16:58 GMT 1
I first began documenting structs May 29, 2013 and now *finally* we can do typedef structures with a pointer too! which means the low level stuff can be done without USEC I hope we can get a typedef RECORD in bacon to improve the syntax even more This was first tested in HUG then converted to a "hybrid" using header free stand alone code with PROTO/PRAGMA gtkhelp how to use typedef structs in bacon wiki.basic-converter.org/index.php?title=Gtkhelphere is some working demo code wiki.basic-converter.org/index.php?title=Gdk-events.bac
|
|
|
Post by bigbass on Oct 18, 2015 6:36:57 GMT 1
developer.gnome.org/gdk3/stable/gdk3-Event-Structures.htmlIn bacon we have reduced and modified several things that we need our own help file for structs Let's focus on typdef structsA new GUI called zahnrad uses its own typedefs Porting to BaCon could be tricky but doable Using gtk as an example only struct GdkEventKey in C
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; };
BaCon code we can embed a typedef struct however the syntax is a bit different notice the types and that int type; and void *window; replaces the GdkEventType type; GdkWindow *window; because those are declared only in the headers and were changed for HUG typedef struct { \ int type; \ void *window; \ signed char send_event; \ unsigned int time; \ unsigned int state; \ unsigned int keyval;}(GdkEventKey)
Describes a key press or key release event. int type; the type of the event (GDK_KEY_PRESS or GDK_KEY_RELEASE). void *window; the window which received the event. signed char send_event; TRUE if the event was sent explicitly. unsigned int time; the time of the event in milliseconds unsigned int state; a bit-mask representing the state of the modifier keys (e.g. Control, Shift and Alt) and the pointer buttons. See GdkModifierType.[type GdkModifierType] unsigned int keyval; the key that was pressed or released. See the gdk/gdkkeysyms.h header file for a complete list of GDK key codes. THESE WERE REMOVED but could be added back by changing the types length; *string; guint16 hardware_keycode; guint8 group; guint is_modifier : 1; GTK does this differently because of the union A GdkEvent contains a union of all of the event types, and allows access to the data fields in a number of ways. The event type is always the first field in all of the event types, and can always be accessed with the following code, no matter what type of event it is: GdkEvent *event; GdkEventType type;
type = event->type
In BaCon there is no *event because we dont use the union we get around this by using a typedef struct called GdkEventKey directly then point to it in this example we use keypress the reason we use (char *) is for BaCon's PRINT to work '---GdkEventKey* keypress; LOCAL keypress TYPE GdkEventKey* key_name$=(char *)gdk_keyval_name(keypress->keyval) PRINT key_name$
Now a real example
'Note: Gdk-events.bac gets the low 'level keypress,mouse buttons and 'scroll wheel 'but this is header free code with 'typedef structs for the first 'time stand alone code
'--- Needed for gtk2 PRAGMA LDFLAGS gtk-x11-2.0 PRAGMA LDFLAGS gdk-x11-2.0 '--- Needed to connect signals PRAGMA LDFLAGS gobject-2.0
'--- GTK PROTO gtk_init ALIAS INIT PROTO gtk_main ALIAS DISPLAY PROTO gtk_widget_show ALIAS SHOW PROTO gtk_window_new ALIAS WINDOW PROTO gtk_exit ALIAS QUIT PROTO gtk_window_set_title ALIAS TITLE PROTO gtk_window_set_default_size ALIAS WINDOW_SIZE
'---extras PROTO g_signal_connect_data ALIAS CALLBACK
'--- GDK PROTO gdk_keyval_name PROTO gdk_event_get_type PROTO gdk_keyval_to_unicode
'--- set undeclared values GTK_WINDOW_TOPLEVEL = 0 GTK_ORIENTATION_VERTICAL = 1
CONST GDK_KEY_PRESS_MASK = 1 << 10 CONST GDK_POINTER_MOTION_MASK = 1 << 2 CONST GDK_SCROLL_MASK = 1 << 21 CONST GDK_BUTTON_PRESS_MASK = 1 << 8 CONST GDK_BUTTON_RELEASE_MASK = 1 << 9 CONST G_CONNECT_AFTER = 1 << 0 GLOBAL NUL TYPE STRING
'---Global properties of the HUG GUI GLOBAL RECORD hug_gui_properties LOCAL last_key_pressed, timeout_id, canvas, freeze, canvasid LOCAL mousex, mousey, scroll, button TYPE int LOCAL options$, gl$, clip$ TYPE STRING END RECORD
'====================================================================== FUNCTION hug_key_press(NUMBER hug_widget, void *hug_data1, NUMBER hug_data2) '====================================================================== REM should work for GTK 1.x and 2.x 3.x '--- The big problem of typedef structs with pointers ! PROTO typedef,struct typedef struct { int type; \ void *window; \ signed char send_event; \ unsigned int time; \ unsigned int state; \ unsigned int keyval;}(GdkEventKey) '---GdkEventKey* keypress; LOCAL keypress TYPE GdkEventKey* keypress = (GdkEventKey*)hug_data1 hug_gui_properties.last_key_pressed = keypress->keyval key_name$=(char *)gdk_keyval_name(keypress->keyval) PRINT key_name$ TITLE(window, key_name$)
RETURN FALSE
END FUNCTION
'====================================================================== SUB hug_mouse_event (NUMBER hug_widget, NUMBER hug_data, long hug_user) '======================================================================
PROTO gtk_widget_set_events PROTO gdk_window_get_pointer
LOCAL gdk, x, y '---leave-notify-event IF hug_user = 30 THEN hug_gui_properties.scroll = -1 hug_gui_properties.button = -1 hug_gui_properties.mousex = -1 hug_gui_properties.mousey = -1 ELSE
hug_gui_properties.canvasid = hug_widget
REM Works for GTK 2.x '--- The big problem of typedef structs with pointers ! PROTO typedef,struct typedef struct {int type; \ void *window; \ signed char send_event; \ unsigned int time; \ double x; \ double y; \ unsigned int state; \ int direction; }(GdkEventScroll)
LOCAL mousescroll TYPE GdkEventScroll* mousescroll = (GdkEventScroll*)hug_data IF (hug_user == 10) THEN hug_gui_properties.scroll = mousescroll->direction ELSE hug_gui_properties.scroll = -1 '--- The big problem of typedef structs with pointers ! typedef struct {int type; \ void *window; \ signed char send_event; \ unsigned int time; \ double x; \ double y; \ double *axes; \ unsigned int state; \ unsigned int button; \ void *device;} (GdkEventButton)
LOCAL mousebutton TYPE GdkEventButton* mousebutton = (GdkEventButton*)hug_data IF (hug_user == 40) THEN hug_gui_properties.button = mousebutton->button ELSE IF (hug_user == 20) THEN hug_gui_properties.button = -1
REM always get position gdk = gdk_window_at_pointer(ADDRESS(x), ADDRESS(y)) gdk_window_get_pointer(gdk, ADDRESS(hug_gui_properties.mousex), ADDRESS(hug_gui_properties.mousey),0) END IF
'PRINT "Mouse x = ",hug_gui_properties.mousex 'PRINT "Mouse y = ",hug_gui_properties.mousey
SELECT hug_gui_properties.scroll CASE 0 PRINT "UP" TITLE(window, "UP") CASE 1 PRINT "DOWN" TITLE(window, "DOWN") DEFAULT 0 END SELECT
SELECT hug_gui_properties.button CASE 1 PRINT "one" TITLE(window, "Mouse one") CASE 2 PRINT "two" TITLE(window, "Mouse two") CASE 3 PRINT "three" TITLE(window, "Mouse three") DEFAULT 0 END SELECT
END SUB
'===================== SUB exit_prog '===================== PRINT "QUIT" QUIT END SUB
INIT (0, 0) window = WINDOW(GTK_WINDOW_TOPLEVEL) WINDOW_SIZE(window, 230, 150) TITLE(window, "get key press") gtk_widget_set_events(window, GDK_KEY_PRESS_MASK |GDK_BUTTON_PRESS_MASK |GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK)
CALLBACK(window, "delete-event", exit_prog, 0, 0, 0) CALLBACK(window, "key-release-event", hug_key_press, 0, 0, 0)
'CALLBACK(window, "button-press-event", hug_mouse_event, 20, 0, 0) CALLBACK(window, "button-release-event", hug_mouse_event, 40, 0, 0) CALLBACK(window, "motion-notify-event", hug_mouse_event, 0, 0, 0) CALLBACK(window, "scroll-event", hug_mouse_event, 10, 0, 0) CALLBACK(window, "leave-notify-event", hug_mouse_event, 30, 0, 0) SHOW(window) DISPLAY
|
|
|
Post by bigbass on Aug 29, 2017 16:35:54 GMT 1
Hey guys
Now that we can compile c++ code to some degree We need to be able to get the structs to do some tests and also to test the compiler directly and cleanly without a GUI lib
PRAGMA INCLUDE <iostream> PRAGMA LDFLAGS PRAGMA COMPILER g++ PRAGMA OPTIONS -Wno-write-strings -Wno-pointer-arith PRAGMA BACONLIB
OPTION PARSE FALSE
std::cout << "Hello BaCon c++ World";
PRINT
'--- use a struct declare floating point member and a string member struct programming { double constant; char * pointer; } (variable) ; variable.constant = 1.23 variable.pointer = "Programming in Software Development."
std::cout <<variable.constant ; PRINT
std::cout <<variable.pointer ;
|
|
|
Post by vovchik on Aug 29, 2017 17:07:46 GMT 1
Dear Joe, Thanks for the example. It works. You only need that "Rebuild Bacon archive" option the first time during a compile session. Subsequent compiles will use the existing .a file, if it exists and "cough" if it doesn't. With kind regards, vovchik
|
|
|
Post by Pjot on Aug 29, 2017 18:14:01 GMT 1
Folks,
There also is a way to force the BaCon library creation programmatically by using this line of code:
PRAGMA BACONLIB
In the next release there will be a C++ version of the BaCOn library archive, created by default during installation time. We then can use the '-lbacon++' link flag instead. Or use the PRAGMA directive again:
PRAGMA LDFLAGS -lfltk -lfltk_images -lbacon++
This will work starting from 3.6.1.
BR peter
|
|
|
Post by bigbass on Aug 30, 2017 18:41:05 GMT 1
Hello Peter
Thanks
I Think that adding PRAGMA BACONLIB to the code is the best solution I will edit my above post with the new line of code
sorry for a late response
P.S I would imagine you have some test snippets for bacon compiling pure c++ code
A humble suggestion if you do have some test code could you link to it / post some basic stuff I would like to see how you get around with using Bacons PRINT
the only way I could get it to work is like this
convertprint$ = (char*)Book1.title PRINT convertprint$
Is there a better way ?
or maybe a new command PRINTC that prints it as a string without manually adding (char*)
PRINTC Book1.title
Thanks
Joe
|
|