C/C++

C, C++, E?

Fórumok

Debian rendszerben letöltöttem néhány minimális konverziós utility-t, ami nagyon hasznos lenne számomra. A többsége egyszerű C program, és sikeresen le is fordulnak, de van köztük pár ".e" kiterjesztésű. Ezekkel nem tudok mit kezdeni. Próbáltam, utánakeresni, lefordítani gcc, g++ segítségével, de egyelőre sikertelenül.

Van esélyem ezeket a fájlokat lefordítani különösebb varázslat nélkül? Mi ez az E egyáltalán? Ez tényleg valami C++ fejlesztés, mint a D? (D programokat már írtam, de ahhoz külön fordító kellett.)

Tud valaki segíteni, hogy ezt a pár ".e" konvertert le tudjam fordítani linux környezetben?

Minden információt megköszönök a témában!

Egyszerű, multiplatform UI toolkit

Fórumok
Kerestem egy egyszerűen használható UI toolkit-et ANSI C-ben, és a Nuklear-t találtam (a C++ megfelelője az ImGui, de az nem használható ANSI C-ből). Nem tudom, hányan ismeritek ezeket, de én nagyon felhúztam magam rajtuk, csupa hazugság a Nuklear. Állítólag kicsi (hát rohadtul nem, a 18000 SLoC az nagyon nem kevés), állítólag hatékony (hát rohadtul nem, folyamatosan memóriát allokálgat és minden képkockánál kovertálgatni kell OpenGL esetén), és állítólag könnyen integrálható (hát rohadtul nem, gyakorlatilag minden glue kódot a nulláról magadnak kell megírni). Ja, és ez az immediate-mode konkrétan egy használhatatlan koncepció, multithreading esélytelen vele például. Ja, és még egy: kurvára nem is C89-ben íródott, hazudik a a README-je... Szóval, hogy rövidre fogjam, csináltam egy UI toolkitet, ami valóban tudja mindazt, amit a Nuklear igér, de képtelen teljesíteni. SMGUI - Státusz-Módú GUI (nem immediate-mode és nem is callback-driven, csak hivatkozni kell a már meglévő változóidra és kész) - egyaránt használható ANSI C és C++ forrásokból is - Egyetlen, függőségmentes fejlécfájl (plusz opcionális modulok) - Platform és backend független (a repóban GLFW3, SDL2/3 és X11 illesztő modulok találhatók, ezek tartalmazzák a glue kódot) - Bármilyen fontot képes kezelni (a repóban PC Screen Font (amit a Linux Console használ) és vektor fontokhoz SSFN modul található) - Kis kódbázis (tényleg, mindössze kb. 2500 SLoC) - Kevés memóriát eszik (gyakorlatilag csak ablak átméretezésnél allokál memóriát, képernyő méretűt és ennyi) - Könnyen integrálható (kb. 5 sornyi kóddal) - HTML flow-szerű, flexibilis elrendezés - Bővíthető a kódodból új widgetekkel (példának egy On-Screen Keyboard-os szövegbeviteli mező van a repóban) - UTF-8 és többnyelvűség támogatás (a nyelv akár menet közben is változtatható) - teljes UNICODE támogatás (ami a Nuklear font bakerével képtelenség, túl sok az a 0x10FFFF darab glif egyetlen textúrához) - multithreading támogatás (ami immediate-mode esetén képtelenség) - természetesen magyar nyelvű doksival: https://bztsrc.gitlab.io/smgui/index.hu.html A licensze MIT, szóval szabadon beépíthető akár fizetős alkalmazásokba is.

[MEGOLDVA] Milyen rand algoritmust használ a C++ Windows alatt?

Fórumok
Újabb hülye kérdés a részemről :-) Szóval, melyik pszeudo-random algoritmust használja a Windows alatt az MSVC-vel fordított C++ srand() / rand()? Kicsit nyomoztam, az MS doksiban azt írták, hogy a Mersenne Twister egyik változata, az MT19937, de nem (ez alapján nem ugyanaz, legalábbis mingw-vel). A másik helyen meg azt olvastam, hogy C++11 óta a Park-Miller, de az sem. Sőt, nem is a Lehner LCG. Na de akkor melyik? Nem az, ami a Linux-os glibc beli, az biztos. Egyébként az is kérdés, van különbség Windows alatt a C-beli rand() és a C++-beli között? Mármint látszatra nem ugyanaz az implementációjuk, de ha C-ben és C++-ban is lefordítok egy minimál programot, akkor ugyanaz az eredményük. Létezik, hogy itt még a mingw is bekavarhat? Mármint a a mingw a Windows-os rand()-ot használja egyáltalán, vagy saját implementációja van abban a libstdc++-ban, amit behúz? Nem azonos a Linux-os glibc-vel, az tuti, de abban nem vagyok biztos, hogy az MSVC-fel fordítottal azonos-e egyáltalán. Ha számít a fordító és a nyelv is, akkor pontosítok: az MSVC C++ fordító által, a "windows.h" fejléc behúzásakor elérhető srand() és rand() algoritmusa kellene. (Itt egyénként az sem világos, hogy ez a "random" fejlécet, avagy a "cstdlib" fejlécet húzza-e be, merthogy mindkettőben van egy rand(), és nem azonosak.) És hogy miért kéne: a gondom az, hogy egy jelenlegi Windows-only megoldást próbálok cross-platformként reprodukálni, ami egy voxel világot generál. Sajnos az algoritmusa rand()-ot használ, így hiába ugyanaz a seed érték, Windows és Linux alatt tök más az eredmény, ami nem jó. Ezért akarom kicserélni Linux alatt az srand()-ot és rand()-ot pontosan ugyanarra az implementációra, amit a Windows használ, hogy hordozható legyen az eredmény. Remélem érhető. Szerk: bakker, mekkora mázlim van, véletlenül belenyúltam a a tutiba az egyik stackoverflow oldal eldugott komment szekciójában! Nem a Lehner, nem is a Park-Miller, hanem egy 1958-as LCG variációt használ, konkrétan ezt:
static int random_seed;

void msvc_cpp_srand(int seed) {
    random_seed = seed;
}

int msvc_cpp_rand() {
    random_seed = (random_seed * 214013 + 2531011) & 0xFFFFFFFF;
    return (random_seed >> 16) & 0x7FFF;
}
Azt továbbra sem tudom, hogy a "windows.h" akkor most a cstdlib-et vagy a random-ot használja-e (illetve azt már tudom, hogy a mingw egyiket sem, külön állatfaj), de már nem is fontos, mivel megvan ez a két konkrét függvény :-) ---------------------------------------------------------------------------------------------------------------------- PONTOSÍTÁS Szükségét látom tisztázni, mert sokakat félrevezetett (elsőre engem is), hogy az eredeti programban nincs véletlenszám generálás, sőt mi több, valódi véletlenszámokkal garantáltan működésképtelen lenne. Amire valójában szüksége van, az egy megbízható, kiszámítható bitshuffler. Az, hogy az eredeti fejlesztő erre a rand()-ot használta, csak mert az épp akkor aktuális cstdlib-jében az egy bitshufflerként volt/van implementálva, na az a csillámfaszlámaság csimborasszója.

X11 matatás Xlib nélkül

Fórumok
Érdekes szösszenet, bár hasznát venni sosem fogom, de mégis lekötött, szerintem roppant tanulságos. https://hereket.com/posts/from-scratch-x11-windowing/ Hogyan nyissunk X11 ablakot és írjuk rá, hogy "Helló világ", majd fogadjunk event-eket, mindössze 200 sornyi C kódból, bármiféle lib vagy header használata nélkül, csakis közvetlen socket írás / olvasással (POSIX headerök és libc azért kell neki, de semmi más).
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>


int32_t GlobalId = 0;
int32_t GlobalIdBase = 0;
int32_t GlobalIdMask = 0;
int32_t GlobalRootWindow = 0;
int32_t GlobalRootVisualId = 0;

int32_t GlobalTextOffsetX = 10;
int32_t GlobalTextOffsetY = 20;

#define READ_BUFFER_SIZE 16*1024

#define RESPONSE_STATE_FAILED 0
#define RESPONSE_STATE_SUCCESS 1
#define RESPONSE_STATE_AUTHENTICATE 2

#define X11_REQUEST_CREATE_WINDOW 1
#define X11_REQUEST_MAP_WINDOW 8
#define X11_REQUEST_IMAGE_TEXT_8 76
#define X11_REQUEST_OPEN_FONT 45
#define X11_REQUEST_CREATE_GC 55


#define X11_EVENT_FLAG_KEY_PRESS 0x00000001
#define X11_EVENT_FLAG_KEY_RELEASE 0x00000002
#define X11_EVENT_FLAG_EXPOSURE 0x8000


#define WINDOWCLASS_COPYFROMPARENT 0
#define WINDOWCLASS_INPUTOUTPUT 1
#define WINDOWCLASS_INPUTONLY 2

#define X11_FLAG_BACKGROUND_PIXEL 0x00000002 
#define X11_FLAG_WIN_EVENT 0x00000800 

#define X11_FLAG_FG 0x00000004
#define X11_FLAG_BG 0x00000008
#define X11_FLAG_FONT 0x00004000
#define X11_FLAG_GC_EXPOSURE 0x00010000

#define PAD(N) ((4 - (N % 4)) % 4)

void VerifyOrDie(int IsSuccess, const char *Message) {
    if(!IsSuccess)  {
        fprintf(stderr, "%s", Message);
        exit(13);
    }
}

void VerifyOrDieWidthErrno(int IsSuccess, const char *Message) {
    if(!IsSuccess)  {
        perror(Message);
        exit(13);
    }
}

void DumpResponseError(int Socket, char* ReadBuffer) {
        uint8_t ReasonLength = ReadBuffer[1];
        uint16_t MajorVersion = *((uint16_t*)&ReadBuffer[2]);
        uint16_t MinorVersion = *((uint16_t*)&ReadBuffer[4]);
        uint16_t AdditionalDataLength = *((uint16_t*)&ReadBuffer[6]); // Length in 4-byte units of "additional data"
        uint8_t *Message = (uint8_t*)&ReadBuffer[8];

        int BytesRead = read(Socket, ReadBuffer + 8, READ_BUFFER_SIZE-8);

        printf("State: %d\n", ReadBuffer[0]);
        printf("MajorVersion: %d\n", MajorVersion);
        printf("MinorVersion: %d\n", MinorVersion);
        printf("AdditionalDataLength: %d\n", AdditionalDataLength);
        printf("Reason: %s\n", Message);
}

void AuthenticateX11() {
    fprintf(stderr, "Current version of the app does not support authentication.\n");
    fprintf(stderr, "Please run 'xhost +local:' in your terminal to disable cookie based authentication\n");
    fprintf(stderr, "and allow local apps to communication with Xorg without it.");
}

int32_t GetNextId() {
    int32_t Result = (GlobalIdMask & GlobalId) | GlobalIdBase;
    GlobalId += 1;
    return Result;
}

void PrintResponseError(char *Data, int32_t Size) {
    char ErrorCode = Data[1];
    const char *ErrorNames[] = {
        "Unknown Error",
        "Request",
        "Value",
        "Window",
        "Pixmap",
        "Atom",
        "Cursor",
        "Font",
        "Match",
        "Drawable",
        "Access",
        "Alloc",
        "Colormap",
        "GContext",
        "IDChoice",
        "Name",
        "Length",
        "Implementation",
    };

    const char* ErrorName = "Unknown error";
    if(ErrorCode < sizeof(ErrorNames) / sizeof(ErrorNames[0])) {
        ErrorName = ErrorNames[ErrorCode];
    }

    
    uint16_t Minor = *((uint16_t*)&Data[8]);
    uint8_t Major = *((uint8_t*)&Data[10]);

    printf("\033[0;31m");
    printf("Response Error: [%d] %s", ErrorCode, ErrorName);
    printf("	Minor: %d, Major: %d", Minor, Major);
    printf("\033[0m\n");


}

void PrintAndProcessEvent(char *Data, int32_t Size) {
    char EventCode = Data[0];
    const char* EventNames[] = {
        "-- Wrong Event Code --",
        "-- Wrong Event Code --",
        "KeyPress",
        "KeyRelease",
        "ButtonPress",
        "ButtonRelease",
        "MotionNotify",
        "EnterNotify",
        "LeaveNotify",
        "FocusIn",
        "FocusOut",
        "KeymapNotify",
        "Expose",
        "GraphicsExposure",
        "NoExposure",
        "VisibilityNotify",
        "CreateNotify",
        "DestroyNotify",
        "UnmapNotify",
        "MapNotify",
        "MapRequest",
        "ReparentNotify",
        "ConfigureNotify",
        "ConfigureRequest",
        "GravityNotify",
        "ResizeRequest",
        "CirculateNotify",
        "CirculateRequest",
        "PropertyNotify",
        "SelectionClear",
        "SelectionRequest",
        "SelectionNotify",
        "ColormapNotify",
        "ClientMessage",
        "MappingNotify",
    };

#define REPLY_EVENT_CODE_KEY_PRESS 2
#define REPLY_EVENT_CODE_EXPOSE 12

const char* TERMINAL_TEXT_COLOR_RED = "\033[0;32m";
const char* TERMINAL_TEXT_COLOR_CLEAR = "\033[0m";

    if(EventCode == REPLY_EVENT_CODE_EXPOSE) {
        // NOTE: Exposure event
        const char *EventName = "Expose";
        uint16_t SequenceNumber = *((uint16_t*)&Data[2]);
        uint32_t Window = *((uint32_t*)&Data[4]);
        uint16_t X = *((uint16_t*)&Data[8]);
        uint16_t Y = *((uint16_t*)&Data[10]);
        uint16_t Width = *((uint16_t*)&Data[12]);
        uint16_t Height = *((uint16_t*)&Data[14]);
        uint16_t Count = *((uint16_t*)&Data[16]);

        printf(TERMINAL_TEXT_COLOR_RED);
            printf("%s: ", EventName);
        printf(TERMINAL_TEXT_COLOR_CLEAR);

        printf("Seq %d, ", SequenceNumber);
        printf("Win %d: ", Window);
        printf("X %d: ", X);
        printf("Y %d: ", Y);
        printf("Width %d: ", Width);
        printf("Height %d: ", Height);
        printf("Count %d: ", Count);
        printf("\n");
        /* printf("%s: Seq %d\n", EventName, SequenceNumber); */
    } else if(EventCode == REPLY_EVENT_CODE_KEY_PRESS) {
        const char *EventName = "KeyPress";
        char KeyCode = Data[1];
        uint16_t SequenceNumber = *((uint16_t*)&Data[2]);
        uint32_t TimeStamp = *((uint32_t*)&Data[4]);
        uint32_t RootWindow = *((uint32_t*)&Data[8]);
        uint32_t EventWindow = *((uint32_t*)&Data[12]);
        uint32_t ChildWindow = *((uint32_t*)&Data[16]); // NOTE: Always 0
        int16_t RootX = *((int16_t*)&Data[20]);
        int16_t RootY = *((int16_t*)&Data[22]);
        int16_t EventX = *((int16_t*)&Data[24]);
        int16_t EventY = *((int16_t*)&Data[26]);
        int16_t SetOfKeyButMask = *((int16_t*)&Data[28]);
        int8_t IsSameScreen = *((int8_t*)&Data[30]);

        printf(TERMINAL_TEXT_COLOR_RED);
            printf("%s: ", EventName);
        printf(TERMINAL_TEXT_COLOR_CLEAR);

        // NOTE: Temporary hack that will not work everywhere
        int StepSize = 10;
        if(KeyCode == 25) { GlobalTextOffsetY += StepSize; }
        if(KeyCode == 39) { GlobalTextOffsetY -= StepSize; }
        if(KeyCode == 38) { GlobalTextOffsetX -= StepSize; }
        if(KeyCode == 40) { GlobalTextOffsetX += StepSize; }

        printf("Code %u, ", (uint8_t)KeyCode);
        printf("Seq %d, ", SequenceNumber);
        printf("Time %d, ", TimeStamp);
        printf("Root %d, ", RootWindow);
        printf("EventW %d, ", EventWindow);
        printf("Child %d, ", ChildWindow);
        printf("RX %d, ", RootX);
        printf("RY %d, ", RootY);
        printf("EX %d, ", EventX);
        printf("EY %d, ", EventY);
        printf("\n");
    } else {
        const char* EventName = " - Unknown Event Code -";
        if(EventCode < sizeof(EventNames) / sizeof(EventNames[0])) {
            EventName = EventNames[EventCode];
        }
        // printf("-------------Event: %s\n", EventName);
        // for(int i = 0; i < Size; i++) {
            // printf("%c", Data[i]);
        // }
        // printf("\n");
    }

}

void GetAndProcessReply(int Socket) {
    char Buffer[1024] = {};
    int32_t BytesRead = read(Socket, Buffer, 1024);

    uint8_t Code = Buffer[0];

    if(Code == 0) {
        PrintResponseError(Buffer, BytesRead);
    } else if (Code == 1) {
        printf("---------------- Unexpected reply\n");
    } else {
        // NOTE: Event?
        PrintAndProcessEvent(Buffer, BytesRead);
    }
}

int X_InitiateConnection(int Socket) { 
    // TODO: Remove global variables and put them into 'connection' struct.
    int SetupStatus = 1;
    char SendBuffer[16*1024] = {};
    char ReadBuffer[16*1024] = {};

    uint8_t InitializationRequest[12] = {};
    InitializationRequest[0] = 'l';
    InitializationRequest[1] = 0;
    InitializationRequest[2] = 11;

    int BytesWritten = write(Socket, (char*)&InitializationRequest, sizeof(InitializationRequest));
    VerifyOrDie(BytesWritten == sizeof(InitializationRequest), "Wrong amount of bytes written during initialization");

    int BytesRead = read(Socket, ReadBuffer, 8);

    if(ReadBuffer[0] == RESPONSE_STATE_FAILED) {
        DumpResponseError(Socket, ReadBuffer);
    }
    else if(ReadBuffer[0] == RESPONSE_STATE_AUTHENTICATE) {
        AuthenticateX11();
    }
    else if(ReadBuffer[0] == RESPONSE_STATE_SUCCESS) {
        printf("INIT Response SUCCESS. BytesRead: %d\n", BytesRead);

        BytesRead = read(Socket, ReadBuffer + 8, READ_BUFFER_SIZE-8);
        printf("---------------------------%d\n", BytesRead);

        /* -------------------------------------------------------------------------------- */
        uint8_t _Unused = ReadBuffer[1];
        uint16_t MajorVersion = *((uint16_t*)&ReadBuffer[2]);
        uint16_t MinorVersion = *((uint16_t*)&ReadBuffer[4]);
        uint16_t AdditionalDataLength = *((uint16_t*)&ReadBuffer[6]); // Length in 4-byte units of "additional data"

        uint32_t ResourceIdBase = *((uint32_t*)&ReadBuffer[12]);
        uint32_t ResourceIdMask = *((uint32_t*)&ReadBuffer[16]);
        uint16_t LengthOfVendor = *((uint16_t*)&ReadBuffer[24]);
        uint8_t NumberOfFormants = *((uint16_t*)&ReadBuffer[29]);
        uint8_t *Vendor = (uint8_t *)&ReadBuffer[40];

        int32_t VendorPad = PAD(LengthOfVendor);
        int32_t FormatByteLength = 8 * NumberOfFormants;
        int32_t ScreensStartOffset = 40 + LengthOfVendor + VendorPad + FormatByteLength;

        uint32_t RootWindow = *((uint32_t*)&ReadBuffer[ScreensStartOffset]);
        uint32_t RootVisualId = *((uint32_t*)&ReadBuffer[ScreensStartOffset + 32]);

        GlobalIdBase = ResourceIdBase;
        GlobalIdMask = ResourceIdMask;
        GlobalRootWindow = RootWindow;
        GlobalRootVisualId = RootVisualId;

        SetupStatus = 0;
    }

    return SetupStatus;
}

int X_CreatWindow(int Socket, int X, int Y, int Width, int Height) {
    // TODO: Put this into 'connection' struct
    char SendBuffer[16*1024] = {};
    char ReadBuffer[16*1024] = {};

    int32_t WindowId = GetNextId();
    int32_t Depth = 0;
    uint32_t BorderWidth = 1;
    int32_t CreateWindowFlagCount = 2;
    int RequestLength = 8+CreateWindowFlagCount;

    SendBuffer[0] = X11_REQUEST_CREATE_WINDOW;
    SendBuffer[1] = Depth;
    *((int16_t *)&SendBuffer[2]) = RequestLength;
    *((int32_t *)&SendBuffer[4]) = WindowId;
    *((int32_t *)&SendBuffer[8]) = GlobalRootWindow;
    *((int16_t *)&SendBuffer[12]) = X;
    *((int16_t *)&SendBuffer[14]) = Y;
    *((int16_t *)&SendBuffer[16]) = Width;
    *((int16_t *)&SendBuffer[18]) = Height;
    *((int16_t *)&SendBuffer[20]) = BorderWidth;
    *((int16_t *)&SendBuffer[22]) = WINDOWCLASS_INPUTOUTPUT;
    *((int32_t *)&SendBuffer[24]) = GlobalRootVisualId;
    *((int32_t *)&SendBuffer[28]) = X11_FLAG_WIN_EVENT | X11_FLAG_BACKGROUND_PIXEL;
    *((int32_t *)&SendBuffer[32]) = 0xff000000;
    *((int32_t *)&SendBuffer[36]) = X11_EVENT_FLAG_EXPOSURE | X11_EVENT_FLAG_KEY_PRESS;

    int BytesWritten = write(Socket, (char *)&SendBuffer, RequestLength*4);

    return WindowId;
}

int X_MapWindow(int Socket, int WindowId) {
    // TODO: Put this into 'connection' struct
    char SendBuffer[16*1024] = {};
    char ReadBuffer[16*1024] = {};

    SendBuffer[0] = X11_REQUEST_MAP_WINDOW;
    SendBuffer[1] = 0;
    *((int16_t *)&SendBuffer[2]) = 2;
    *((int32_t *)&SendBuffer[4]) = WindowId;

    int BytesWritten = write(Socket, (char *)&SendBuffer, 2*4);
    return 0;
}

void X_OpenFont(int32_t Socket, char *FontName, int32_t FontId) {
    char SendBuffer[16*1024] = {};
    char ReadBuffer[16*1024] = {};
    int BytesWritten = 0;
    int BytesRead = 0;

    int32_t FontNameLength = strlen((char *)FontName);
    int32_t Pad = PAD(FontNameLength);
    int RequestLength = (3 + (FontNameLength + Pad)/4);

    SendBuffer[0] = X11_REQUEST_OPEN_FONT;
    SendBuffer[1] = 0;
    *((uint16_t *)&SendBuffer[2]) = RequestLength;
    *((uint32_t *)&SendBuffer[4]) = FontId;
    *((uint16_t *)&SendBuffer[8]) = FontNameLength;
    strncpy(SendBuffer + 12, (char *)FontName, FontNameLength);

    int32_t WriteSize = 12 + FontNameLength + Pad;
    BytesWritten = write(Socket, (char *)&SendBuffer, WriteSize);
}

void X_CreateGC(int32_t Socket, int32_t GcId, int32_t FontId) {
    char SendBuffer[16*1024] = {};

    int32_t CreateGcFlagCount = 3;
    int RequestLength = 4 + CreateGcFlagCount;

    SendBuffer[0] = X11_REQUEST_CREATE_GC;
    SendBuffer[1] = 0;
    *((int16_t *)&SendBuffer[2]) = RequestLength;
    *((int32_t *)&SendBuffer[4]) = GcId;
    *((int32_t *)&SendBuffer[8]) = GlobalRootWindow;
    *((int32_t *)&SendBuffer[12]) = X11_FLAG_FG | X11_FLAG_BG | X11_FLAG_FONT;
    *((int32_t *)&SendBuffer[16]) = 0xFF00FF00; // Foreground
    *((int32_t *)&SendBuffer[20]) = 0xFF000000; // Background
    *((int32_t *)&SendBuffer[24]) = FontId; // Font

    write(Socket, (char *)&SendBuffer, RequestLength*4);
}

void WriteText(int Socket, int WindowId, int GCid, int16_t X, int16_t Y, const char *Text, int32_t TextLength) {
    char Buffer[16*1024] = {};

    uint32_t ContentLength = 4 + (TextLength + PAD(TextLength))/4;

    Buffer[0] = (uint8_t)X11_REQUEST_IMAGE_TEXT_8;
    Buffer[1] = TextLength;
    *((int16_t *)&Buffer[2]) = ContentLength; 
    *((int32_t *)&Buffer[4]) = WindowId;
    *((int32_t *)&Buffer[8]) = GCid;
    *((int16_t *)&Buffer[12]) = X; 
    *((int16_t *)&Buffer[14]) = Y; 

    strncpy(&Buffer[16], (char *)Text, TextLength);
    int BytesWritten = write(Socket, (char *)&Buffer, ContentLength*4);
}

int main(){
    int Socket = socket(AF_UNIX, SOCK_STREAM, 0);
    VerifyOrDie(Socket > 0, "Couldn't open a socket(...)");

    struct sockaddr_un Address;
    memset(&Address, 0, sizeof(struct sockaddr_un));
    Address.sun_family = AF_UNIX;
    strncpy(Address.sun_path, "/tmp/.X11-unix/X0", sizeof(Address.sun_path)-1);

    int Status = connect(Socket, (struct sockaddr *)&Address, sizeof(Address));
    VerifyOrDieWidthErrno(Status == 0, "Couldn't connect to a unix socket with connect(...)");

    int SetupStatus = X_InitiateConnection(Socket);

    if(SetupStatus == 0) {
        int32_t X = 100;
        int32_t Y = 100;
        uint32_t Width = 600;
        uint32_t Height = 300;
        int WindowId = X_CreatWindow(Socket, X, Y, Width, Height);

        X_MapWindow(Socket, WindowId);

        int32_t FontId = GetNextId();
        X_OpenFont(Socket, (int8_t *)"fixed", FontId);

        int32_t GcId = GetNextId();
        X_CreateGC(Socket, GcId, FontId);

        struct pollfd PollDescriptors[1] = {};
        PollDescriptors[0].fd = Socket;
        PollDescriptors[0].events = POLLIN;
        int32_t DescriptorCount = 1;
        int32_t IsProgramRunning = 1;
        while(IsProgramRunning){
            int32_t EventCount = poll(PollDescriptors, DescriptorCount, -1);

            if(PollDescriptors[0].revents & POLLERR) {
                printf("------- Error\n");
            }

            if(PollDescriptors[0].revents & POLLHUP) {
                printf("---- Connection close\n");
                IsProgramRunning = 0;
            }

            char* t1 = "Hello, World!";
            char* t2 = "This is a test text directly written to X";
            char* t3 = "Whooha. Is this even legal? Let's keep a secret!";
            WriteText(Socket, WindowId, GcId, GlobalTextOffsetX, GlobalTextOffsetY, t1, strlen(t1));
            WriteText(Socket, WindowId, GcId, GlobalTextOffsetX, GlobalTextOffsetY + 15, t2, strlen(t2));
            WriteText(Socket, WindowId, GcId, GlobalTextOffsetX, GlobalTextOffsetY + 30, t3, strlen(t3));

            GetAndProcessReply(PollDescriptors[0].fd);
        }
    }

}
Fordítás:
gcc main.c -o main
Ennyi! A linkelt blogposztban részletesen el van magyarázva minden, érdemes elolvasni hozzá.

3D modellező egy hét alatt

Fórumok
Nem semmi a csóka, 1 hét alatt összedobott egy komplett 3D modellező programot. Mivel C-ben írta, így gond nélkül wasm-ra is fordítható, és böngészőben is fut. Mindezt szépen le is dokumentálta, tecső videóval, bloggal stb. Külön érdekesség, hogy a videóban azt is elmondja, miért választotta a Signed Distance Field-et a mesh helyett, és remek animációkkal még a működési elvét is elmagyarázza, roppant tanulságos! ví dejó: https://youtu.be/-Xb3Kk3HhIw (akkor is érdemes megnézni, ha nem érdekel a megvalósítás) webdemó: https://danielchasehooper.com/projects/shapeup/ (interaktív, kipróbálható) forrás: https://github.com/danielchasehooper/ShapeUp-public blog: https://danielchasehooper.com/posts/shapeup/ (itt belemegy az implementációs részletekbe is) A blogon egyébként arra is kitér, hogy miért a C-t választotta. SPOILER: pont azokat az érveket hozza fel, amiket már én is jó ideje hangoztatok, pedig nem valószínű. hogy ez a Daniel gyerek sokat olvasná a HUP-ot :-D És mindezt tokkal vonóval 1 hét alatt! (Ebben benne van a videó elkészítése is, ami állítólag tovább tartott, mint a programot megírni)

STM32 arm debuggolás

Fórumok

Bare metal szintről próbálok beletanulni az ST arm alapú processzorainak debuggolásának. A fejlesztő rendszer egy Debian 12 gépen fut.
Az első a tool chain és aztán a jó öreg "blinky" és miután ez működik jöhet a debugger.. Miután fe
Több bare metal ismertetőt átolvastam mindegyik arra fut ki, hogy addjam ki a parancsot:

$ arm-none-eabi-gdb main.elf

Úgy tűnik ez elavult, a tool chain megvan, azonban a gdb ügyében a Debian elküld, hogy telepítsem fel az arm architecturát. Csináltam már ilyesmit, de konkrétan a debuggolás viszonylatában nem :(
Nem találok hozzá leírást.

Ha feltelpítem az arm architecturát hogy indíthatok egy debug sessiont?

STM32F051 CMSIS bare metal header files

Fórumok

Bare metal programming -hoz keresem a megfelelő CMSIS fájlokat, arm-none-eabi tool chain, de eltévedtem az erdőben.

STM32F051 -es MCU-hoz keresem a megfelelő CMSIS fájlokat. Az egyik git repoban találtam olyat, hogy stm32f031x6.h (ezzel sikerült is egy kínai gyártmányú kis panelt a blink-ig felébreszteni).
A google a developper.arm.com -ot dobja fel, de az mintha a keil-hez fűződne ill. valami olyan ide-hez ami kezeli a (számomra szokatlan) .pack fájlt.
Megint a google feldob egy kimondottan az STMicroelectronics "cmsis_core" repót a git-en. Viszont itt nyoma nincs az ilyen nevesített fájloknak amit idéztem, olyat látok benne mint az stm32f0xx.h -t (amit az előzőleg idézett blinky repo is használ).

Két, jónak mondható bare metal programming guide-t is találtam, az egyik a git "cpq" nevével illetve a másik "független" a Vivonomicon sorozata.
Először a cpq verzióval indultam el (persze ott sincs pont az F051 mcu) de még nem sikerült működésre bírni vele a kártyámat.
Találtam egy igen régi csomagot is egy bizonyos "Frank Duignan" blogja - több stm gyártmányú arm-al is foglalkozik, viszont igen régi, és persze nincs ott sem szó az F051-ről.

Hogy lehet összerakni, egy használható fejlesztői CMSIS fájl készletet az STM32F051 -hez?

[lenyegeben megoldva] local/label szimbolumok es/vagy szimbolum-mintak kiszedese

Fórumok

Sziaztok!

Valamiert bizonyos architekturakon (pl msp430) szeret a GCC ilyen .L* lokalis szimbolumokat beletenni a text szegmensbe. Pelda: 

$ nm main.elf | sort 
[...]
0000cb34 t transmit_get_iface_by_name
0000cb3e t .L8
0000cb58 t .L6
0000cb5e T testled_init
[...]

amik szepen megjelennek az objdump + disassembly kimenetben is:

0000cb34 <transmit_get_iface_by_name>:
    cb34:       2a 15           pushm   #3,     r10     ;16-bit words
    cb36:       08 4c           mov     r12,    r8      ;
    cb38:       39 40 5c 20     mov     #8284,  r9      ;#0x205c
    cb3c:       4a 43           clr.b   r10             ;

0000cb3e <.L8>:
    cb3e:       0d 48           mov     r8,     r13     ;
    cb40:       2c 49           mov     @r9,    r12     ;
    cb42:       b0 12 72 f0     call    #-3982          ;#0xf072
    cb46:       0c 93           cmp     #0,     r12     ;r3 As==00
    cb48:       07 24           jz      $+16            ;abs 0xcb58
    cb4a:       1a 53           inc     r10             ;
    cb4c:       39 50 36 00     add     #54,    r9      ;#0x0036
    cb50:       3a 90 06 00     cmp     #6,     r10     ;
    cb54:       f4 23           jnz     $-22            ;abs 0xcb3e
    cb56:       3a 43           mov     #-1,    r10     ;r3 As==11
 
0000cb58 <.L6>:
    cb58:       0c 4a           mov     r10,    r12     ;
    cb5a:       28 17           popm    #3,     r10     ;16-bit words
    cb5c:       30 41           ret
 
0000cb5e <testled_init>:
    cb5e:       d2 d3 04 02     bis.b   #1,     &0x0204 ;r3 As==01
    cb62:       30 41           ret

Ha meg itten ezeket fel is oldana az ugyan legalabb valamit segithet az ertelmezesben (lasd: 0xcb54-es cimen  az a `jnz $-22` ehelyett mondjuk `jnz .L8` is lehetne), de mivel meg az sem, ezert ez ugy erosen ront a kimenetek (nm, objdump) olvashatosagan mar egy kozepes projektnel is... :( Peldaul itten most ennel a projektnel:

$ nm main.elf | grep " T " | wc -l
103
$ nm main.elf | grep ".L" | wc -l
645

azaz minden valodi text szimbolumra jut valamivel tobb mint 6 ilyen label-szeruseg... aztan talaljunk meg valamit itten a szenakazalban...  Szoval az X problema az hogy hogyan lehetne azt elerni hogy ezek mar bele se keruljenek a *.o/*.elf-be, az Y problema pedig hogy hamar belekerultek, hogyan lehet kiszedni es/vagy megszabadulni? Az objcopy peldaul tud section pattern-ekre szurni (lasd: `objcopy -j '*' -j '!.persist*' -j ...`), de szimbolum patternre lehet? Tulajdonkeppen semmi nem erdekel ami .L* :] Mas embedded/cross architekturakon (avr, rv32, armv6/v7) nem lattam meg ilyet, de msp430-nal ez most kifejezetten nyugos ha valami szitu van :/

thx, A.

AddressSanitizer:DEADLYSIGNAL végtelen loop

Fórumok

Hátha érdekel valakit, elkerülendő a szívás ....

Ubuntu 22.04.1, gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0. Az Ubuntu egy i5 Macbookon fut Parallels virtualizáció.

curl 7.81.0 (x86_64-pc-linux-gnu) libcurl/7.81.0 OpenSSL/3.0.2 zlib/1.2.11 brotli/1.0.9 zstd/1.4.8 libidn2/2.3.2 libpsl/0.21.0 (+libidn2/2.3.2) libssh/0.9.6/openssl/zlib nghttp2/1.43.0 librtmp/2.3 OpenLDAP/2.5.17
Release-Date: 2022-01-05

Van két rövid C program(ocska), semmi extra, parancssoros fordítás: gcc -Wall -Werror -pedantic -Wextra -fsanitize=address ... -lcurl -lm, weboldal lekérés és feldolgozás. Fordítás során semmit nem ír ki, nincs hiba, nincs megjegyzés.

A két fájl a fő funkciók tekintetében ugyanaz.

Elindítod az egyik fájlt, minden OK, teszi amit tenni kell, lefut, kilép hiba nélkül.

Elindítod a másodikat, kiírja a konzolra: AddressSanitizer:DEADLYSIGNAL végtelen loop-ban, abba sem akarja hagyni.

 

Megoldás:

sudo sysctl -w vm.mmap_rnd_bits=28

Innen szedtem a megoldást, miután feladtam a kód milliomodik átnézését:

https://stackoverflow.com/questions/77672217/gcc-fsanitize-address-resu…

Egészségetekre!