vsnprintf() fehlt - was wäre der beste workaround?



  • Hallo Forumsbesucher,

    der Titel sagt eigentlich schon alles, ich sitze gerade an einer Portierung, wo dem Target- Compiler die n- limitierten Funktionen aus der printf()- Familie fehlen. Ich habe interimsweise vsprintf() dafür eingesetzt, aber das könnte mir rein theoretisch den Buffer (für eine Zeile Textdisplay) sprengen 😞 . Ich habe jetzt mal hier einen workaround angedeutet, der mir aber nicht gefällt:

    void DisplayText(char far *line, ...)	// Text ausgeben
    {
    #define MAXLEN 60
    	va_list argzeiger;
    	char i;
    	int length;
    	char zeile[MAXLEN];
    	char far *nirvana = NULL;
    
    	va_start(argzeiger, line);
    //	length = vsnprintf(zeile, MAXLEN, line, argzeiger);
    	length = vsprintf(nirvana, line, argzeiger);
    	va_end(argzeiger);
    	if (length < MAXLEN)
    	{
    		va_start(argzeiger, line);
    		length = vsprintf(zeile, line, argzeiger);
    		va_end(argzeiger);
    		length--;
    		for (i=0; i<length; i++ )
    			DisplayData(DisplayCode(zeile[i]));	
    	}
    	else
    	{
    		// Fehlerbehandlung
    	}
    #undef MAXLEN
    }
    

    Erstmal bin ich mir nicht sicher, ob man wirklich durch das Schicken an einen NULL- Pointer die Ausgabe wirklich loswird, ohne Speicher zu belegen. Bilde mir ein, das mal gelesen zu haben, jedenfalls tut's, hab' aber null Ahnung, ob das echt abgedeckt ist oder bei einem anderen Compiler zu Problemen führen kann.

    Zweites Übel ist, daß der Formatstring zweimal geparst würde, ist zwar nur HID, aber an der Mickerkiste merkt man's schon.

    Das dritte Problem ist, daß es immer Fehler geben kann, entweder der fixe Buffer reicht nicht aus, dann tut das Ding gar nix (statt wie vorher einfach brav zu clippen) oder ich muß mir temporär per malloc() Speicher besorgen und aber auch vorsehen, daß das nicht klappt. Wie man's dreht und wendet, es würde von einer void zur errorlevelfunktion, was für den Rest des Codes Folgen hätte.

    Gibt's da nichts Schlaueres? - Vielleicht fällt euch was dazu ein, Danke für's Kopf schiefhalten! 🙂

    PS: Das zweite va_start im if- Block scheint's nicht zu brauchen, ich hatte das vorhin versehentlich auskommentiert und danach die va_ends, das führte zum gleichen Ergebnis - seltsam oder erklärlich?



  • Laut meiner man page:

    Concerning the return value of snprintf(), SUSv2 and C99 contradict each other: when snprintf() is called with size=0 then SUSv2 stipulates an unspecified return value less than 1, while C99 allows str to be NULL in this case, and gives the return value (as always) as the number of characters that would have been written in case the output string has been large enough.

    ansonsten, hast du sowas wie /dev/null ? Dann könntest du statt NULL einen FILE-Pointer auf /dev/null verwenden.



  • supertux schrieb:

    Laut meiner man page: ...

    Sowas war zu befürchten 🙄

    supertux schrieb:

    ansonsten, hast du sowas wie /dev/null ? Dann könntest du statt NULL einen FILE-Pointer auf /dev/null verwenden.

    Leider nicht, das Target ist nur ein Controllerchen ohne Filesystem. Eigentlich möchte ich da nicht mal malloc() im Code haben.
    Ich könnte noch das Standard- Device auf das Display verbiegen und das Clipping dorthin verlagern, wär' aber auch nur Frickelkram, über den man irgendwann stolpert.
    Momentan tendiere ich auch aus Laufzeitgründen zu Methode "Gott zum Gruße", also char- Array fester Größe mit ein wenig Sicherheitsreserve und halt dem Risiko eines Absturzes, das ich dokumentieren muß. Irgendwie unschön ... 😞



  • Um welchen Compiler handelt es sich denn überhaupt? Kennt der möglicherweise die BSD-Funktion vasprintf?

    Ansonsten...wenn es sich lediglich um einen Workaround für einen speziellen Compiler handelt:

    #ifdef DIESER_SPEZIELLE_COMPILER
      /* Workaround */
    #else
      va_start(argzeiger, line);
      vsnprintf(zeile, MAXLEN, line, argzeiger);
      va_end(argzeiger);
    #endif
    

    Üblicherweise definieren Compiler von Haus aus bestimmte Makros, die sie eindeutig identifizieren, etwa __GNUC__ für gcc oder _MSC_VER für MSVC. Welches deiner definiert, steht im Zweifel in seiner Dokumentation.



  • seldon schrieb:

    Um welchen Compiler handelt es sich denn überhaupt? Kennt der möglicherweise die BSD-Funktion vasprintf?

    Nö, leider nicht. 🙄

    .\display.r30 : '_vasprintf' value is undefined
    

    seldon schrieb:

    Ansonsten...wenn es sich lediglich um einen Workaround für einen speziellen Compiler handelt:

    Das war mir schon klar, es ging mir aber um die Ausgestaltung des Workarounds, nicht um dessen Anlage. Ist ein etwas älterer Renesas für R8C. Da sollten irgendwo Sourcen zu den Libs zu finden sein, zumindest war's früher so. Ich grab' da mal weiter.


Anmelden zum Antworten