462 lines
11 KiB
C
462 lines
11 KiB
C
/* strutil.c */
|
|
/*****************************************************************************/
|
|
/* AS-Portierung */
|
|
/* */
|
|
/* haeufig benoetigte String-Funktionen */
|
|
/* */
|
|
/* Historie: 5. 5.1996 Grundsteinlegung */
|
|
/* 13. 8.1997 KillBlanks-Funktionen aus asmsub.c heruebergenommen */
|
|
/* 29. 8.1998 sprintf-Emulation */
|
|
/* 17. 4.1999 strcasecmp gegen Nullzeiger geschuetzt */
|
|
/* 30. 5.1999 ConstLongInt akzeptiert auf 0x fuer Hex-Zahlen */
|
|
/* */
|
|
/*****************************************************************************/
|
|
|
|
#include "stdinc.h"
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
|
|
#include "strutil.h"
|
|
#undef strlen /* VORSICHT, Rekursion!!! */
|
|
#ifdef BROKEN_SPRINTF
|
|
#undef sprintf
|
|
#endif
|
|
|
|
Boolean HexLowerCase; /* Hex-Konstanten mit Kleinbuchstaben */
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* eine bestimmte Anzahl Leerzeichen liefern */
|
|
|
|
char *Blanks(int cnt)
|
|
BEGIN
|
|
static char *BlkStr=" ";
|
|
|
|
if (cnt<0) cnt=0;
|
|
|
|
return BlkStr+(strlen(BlkStr)-cnt);
|
|
END
|
|
|
|
|
|
/****************************************************************************/
|
|
/* eine Integerzahl in eine Hexstring umsetzen. Weitere vordere Stellen als */
|
|
/* Nullen */
|
|
|
|
#define BufferCnt 8
|
|
|
|
char *HexString(LargeWord i, int Stellen)
|
|
BEGIN
|
|
static ShortString h[BufferCnt];
|
|
static int z = 0;
|
|
LargeWord digit;
|
|
char *ptr;
|
|
|
|
if (Stellen > sizeof(ShortString) - 1)
|
|
Stellen = sizeof(ShortString) - 1;
|
|
|
|
ptr = h[z] + sizeof(ShortString) - 1;
|
|
*ptr = '\0';
|
|
do
|
|
BEGIN
|
|
digit = i & 15;
|
|
if (digit < 10)
|
|
*(--ptr) = digit + '0';
|
|
else if (HexLowerCase)
|
|
*(--ptr) = digit - 10 + 'a';
|
|
else
|
|
*(--ptr) = digit - 10 + 'A';
|
|
i = i >> 4;
|
|
Stellen--;
|
|
END
|
|
while ((Stellen > 0) OR (i != 0));
|
|
|
|
z = (z + 1) % BufferCnt;
|
|
|
|
return ptr;
|
|
END
|
|
|
|
char *SysString(LargeWord i, LargeWord System, int Stellen)
|
|
BEGIN
|
|
static ShortString h[BufferCnt];
|
|
static int z = 0;
|
|
LargeWord digit;
|
|
char *ptr;
|
|
|
|
if (Stellen > sizeof(ShortString) - 1)
|
|
Stellen = sizeof(ShortString) - 1;
|
|
|
|
ptr = h[z] + sizeof(ShortString) - 1;
|
|
*ptr = '\0';
|
|
do
|
|
BEGIN
|
|
digit = i % System;
|
|
if (digit < 10)
|
|
*(--ptr) = digit + '0';
|
|
else if (HexLowerCase)
|
|
*(--ptr) = digit - 10 + 'a';
|
|
else
|
|
*(--ptr) = digit - 10 + 'A';
|
|
i /= System;
|
|
Stellen--;
|
|
END
|
|
while ((Stellen > 0) OR (i != 0));
|
|
|
|
z = (z + 1) % BufferCnt;
|
|
|
|
return ptr;
|
|
END
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* dito, nur vorne Leerzeichen */
|
|
|
|
char *HexBlankString(LargeWord i, Byte Stellen)
|
|
BEGIN
|
|
static String temp;
|
|
|
|
strmaxcpy(temp,HexString(i,0),255);
|
|
if (strlen(temp)<Stellen) strmaxprep(temp,Blanks(Stellen-strlen(temp)),255);
|
|
return temp;
|
|
END
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Da manche Systeme (SunOS) Probleme mit der Ausgabe extra langer Ints
|
|
haben, machen wir das jetzt zu Fuss :-( */
|
|
|
|
char *LargeString(LargeInt i)
|
|
BEGIN
|
|
Boolean SignFlag=False;
|
|
static String s;
|
|
String tmp;
|
|
char *p,*p2;
|
|
|
|
if (i<0)
|
|
BEGIN
|
|
i=(-i); SignFlag=True;
|
|
END
|
|
|
|
p=tmp;
|
|
do
|
|
BEGIN
|
|
*(p++)='0'+(i%10);
|
|
i/=10;
|
|
END
|
|
while (i>0);
|
|
|
|
p2=s; if (SignFlag) *(p2++)='-';
|
|
while (p>tmp) *(p2++)=(*(--p));
|
|
*p2='\0'; return s;
|
|
END
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* manche haben's nicht... */
|
|
|
|
#if defined(NEEDS_STRDUP) || defined(CKMALLOC)
|
|
#ifdef CKMALLOC
|
|
char *mystrdup(char *s)
|
|
BEGIN
|
|
#else
|
|
char *strdup(char *s)
|
|
BEGIN
|
|
#endif
|
|
char *ptr=(char *) malloc(strlen(s)+1);
|
|
#ifdef CKMALLOC
|
|
if (ptr==Nil)
|
|
BEGIN
|
|
fprintf(stderr,"strdup: out of memory?\n"); exit(255);
|
|
END
|
|
#endif
|
|
if (ptr!=0) strcpy(ptr,s);
|
|
return ptr;
|
|
END
|
|
#endif
|
|
|
|
#ifdef NEEDS_CASECMP
|
|
int strcasecmp(const char *src1, const char *src2)
|
|
BEGIN
|
|
if (src1 == NULL) src1 = "";
|
|
if (src2 == NULL) src2 = "";
|
|
while (toupper(*src1)==toupper(*src2))
|
|
BEGIN
|
|
if ((NOT *src1) AND (NOT *src2)) return 0;
|
|
src1++; src2++;
|
|
END
|
|
return ((int) toupper(*src1))-((int) toupper(*src2));
|
|
END
|
|
|
|
int strncasecmp(const char *src1, const char *src2, int len)
|
|
BEGIN
|
|
if (src1 == NULL) src1 = "";
|
|
if (src2 == NULL) src2 = "";
|
|
while (toupper(*src1)==toupper(*src2))
|
|
BEGIN
|
|
if (--len==0) return 0;
|
|
if ((NOT *src1) AND (NOT *src2)) return 0;
|
|
src1++; src2++;
|
|
END
|
|
return ((int) toupper(*src1))-((int) toupper(*src2));
|
|
END
|
|
#endif
|
|
|
|
#ifdef NEEDS_STRSTR
|
|
char *strstr(char *haystack, char *needle)
|
|
BEGIN
|
|
int lh=strlen(haystack), ln=strlen(needle);
|
|
int z;
|
|
char *p;
|
|
|
|
for (z=0; z<=lh-ln; z++)
|
|
if (strncmp(p=haystack+z,needle,ln)==0) return p;
|
|
return Nil;
|
|
END
|
|
#endif
|
|
|
|
#ifdef BROKEN_SPRINTF
|
|
#include <varargs.h>
|
|
|
|
int mysprintf(va_alist) va_dcl
|
|
BEGIN
|
|
va_list pvar;
|
|
char *form,*dest,*run;
|
|
|
|
va_start(pvar);
|
|
dest=va_arg(pvar,char*);
|
|
form=va_arg(pvar,char*);
|
|
vsprintf(dest,form,pvar);
|
|
|
|
for (run=dest; *run!='\0'; run++);
|
|
return run-dest;
|
|
END
|
|
#endif
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* wenn man mit unsigned arbeitet, gibt das boese Seiteneffekte bei direkter
|
|
Arithmetik mit strlen... */
|
|
|
|
signed int strslen(const char *s)
|
|
BEGIN
|
|
return strlen(s);
|
|
END
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* das originale strncpy plaettet alle ueberstehenden Zeichen mit Nullen */
|
|
|
|
void strmaxcpy(char *dest, const char *src, int Max)
|
|
BEGIN
|
|
int cnt=strlen(src);
|
|
|
|
if (cnt>Max) cnt=Max;
|
|
memcpy(dest,src,cnt); dest[cnt]='\0';
|
|
END
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* einfuegen, mit Begrenzung */
|
|
|
|
void strmaxcat(char *Dest, const char *Src, int MaxLen)
|
|
BEGIN
|
|
int TLen=strlen(Src),DLen=strlen(Dest);
|
|
|
|
if (TLen>MaxLen-DLen) TLen=MaxLen-DLen;
|
|
if (TLen>0)
|
|
BEGIN
|
|
memcpy(Dest+DLen,Src,TLen);
|
|
Dest[DLen+TLen]='\0';
|
|
END
|
|
END
|
|
|
|
void strprep(char *Dest, const char *Src)
|
|
BEGIN
|
|
memmove(Dest+strlen(Src),Dest,strlen(Dest)+1);
|
|
memmove(Dest,Src,strlen(Src));
|
|
END
|
|
|
|
void strmaxprep(char *Dest, const char *Src, int MaxLen)
|
|
BEGIN
|
|
int RLen;
|
|
|
|
RLen=strlen(Src); if (RLen>MaxLen-strlen(Dest)) RLen=MaxLen-strlen(Dest);
|
|
memmove(Dest+RLen,Dest,strlen(Dest)+1);
|
|
memmove(Dest,Src,RLen);
|
|
END
|
|
|
|
void strins(char *Dest, const char *Src, int Pos)
|
|
BEGIN
|
|
memmove(Dest+Pos+strlen(Src),Dest+Pos,strlen(Dest)+1-Pos);
|
|
memmove(Dest+Pos,Src,strlen(Src));
|
|
END
|
|
|
|
void strmaxins(char *Dest, const char *Src, int Pos, int MaxLen)
|
|
BEGIN
|
|
int RLen;
|
|
|
|
RLen=strlen(Src); if (RLen>MaxLen-strlen(Dest)) RLen=MaxLen-strlen(Dest);
|
|
memmove(Dest+Pos+RLen,Dest+Pos,strlen(Dest)+1-Pos);
|
|
memmove(Dest+Pos,Src,RLen);
|
|
END
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Bis Zeilenende lesen */
|
|
|
|
void ReadLn(FILE *Datei, char *Zeile)
|
|
BEGIN
|
|
/* int Zeichen='\0';
|
|
char *Run=Zeile;
|
|
|
|
while ((Zeichen!='\n') AND (Zeichen!=EOF) AND (!feof(Datei)))
|
|
BEGIN
|
|
Zeichen=fgetc(Datei);
|
|
if (Zeichen!=26) *Run++=Zeichen;
|
|
END
|
|
|
|
if ((Run>Zeile) AND ((Zeichen==EOF) OR (Zeichen=='\n'))) Run--;
|
|
if ((Run>Zeile) AND (Run[-1]==13)) Run--;
|
|
*Run++='\0';*/
|
|
|
|
char *ptr;
|
|
int l;
|
|
|
|
*Zeile='\0'; ptr=fgets(Zeile,256,Datei);
|
|
if ((ptr==Nil) AND (ferror(Datei)!=0)) *Zeile='\0';
|
|
l=strlen(Zeile);
|
|
if ((l>0) AND (Zeile[l-1]=='\n')) Zeile[--l]='\0';
|
|
if ((l>0) AND (Zeile[l-1]=='\r')) Zeile[--l]='\0';
|
|
if ((l>0) AND (Zeile[l-1]==26)) Zeile[--l]='\0';
|
|
END
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
/* Zahlenkonstante umsetzen: $ hex, % binaer, @ oktal */
|
|
/* inp: Eingabezeichenkette */
|
|
/* erg: Zeiger auf Ergebnis-Longint */
|
|
/* liefert TRUE, falls fehlerfrei, sonst FALSE */
|
|
|
|
LongInt ConstLongInt(const char *inp, Boolean *err)
|
|
BEGIN
|
|
static char Prefixes[4]={'$','@','%','\0'}; /* die moeglichen Zahlensysteme */
|
|
static LongInt Bases[3]={16,8,2}; /* die dazugehoerigen Basen */
|
|
LongInt erg;
|
|
LongInt Base=10,z,val,vorz=1; /* Vermischtes */
|
|
|
|
/* eventuelles Vorzeichen abspalten */
|
|
|
|
if (*inp == '-')
|
|
BEGIN
|
|
vorz = (-1); inp++;
|
|
END
|
|
|
|
/* Sonderbehandlung 0x --> $ */
|
|
|
|
if ((strlen(inp) >= 2) && (*inp == '0') && (toupper(inp[1]) == 'X'))
|
|
BEGIN
|
|
inp += 2;
|
|
Base = 16;
|
|
END
|
|
|
|
/* Jetzt das Zahlensystem feststellen. Vorgabe ist dezimal, was
|
|
sich aber durch den Initialwert von Base jederzeit aendern
|
|
laesst. Der break-Befehl verhindert, dass mehrere Basenzeichen
|
|
hintereinander eingegeben werden koennen */
|
|
|
|
else
|
|
for (z = 0; z < 3; z++)
|
|
if (*inp == Prefixes[z])
|
|
BEGIN
|
|
Base = Bases[z]; inp++; break;
|
|
END
|
|
|
|
/* jetzt die Zahlenzeichen der Reihe nach durchverwursten */
|
|
|
|
erg=0; *err=False;
|
|
for(; *inp != '\0'; inp++)
|
|
BEGIN
|
|
/* Ziffern 0..9 ergeben selbiges */
|
|
|
|
if ((*inp>='0') AND (*inp<='9')) val=(*inp)-'0';
|
|
|
|
/* Grossbuchstaben fuer Hexziffern */
|
|
|
|
else if ((*inp>='A') AND (*inp<='F')) val=(*inp)-'A'+10;
|
|
|
|
/* Kleinbuchstaben nicht vergessen...! */
|
|
|
|
else if ((*inp>='a') AND (*inp<='f')) val=(*inp)-'a'+10;
|
|
|
|
/* alles andere ist Schrott */
|
|
|
|
else break;
|
|
|
|
/* entsprechend der Basis zulaessige Ziffer ? */
|
|
|
|
if (val>=Base) break;
|
|
|
|
/* Zahl linksschieben, zusammenfassen, naechster bitte */
|
|
|
|
erg=erg*Base+val;
|
|
END
|
|
|
|
/* bis zum Ende durchgelaufen ? */
|
|
|
|
if (*inp == '\0')
|
|
BEGIN
|
|
/* Vorzeichen beruecksichtigen */
|
|
|
|
erg*=vorz;
|
|
*err=True;
|
|
END
|
|
|
|
return erg;
|
|
END
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* alle Leerzeichen aus einem String loeschen */
|
|
|
|
void KillBlanks(char *s)
|
|
BEGIN
|
|
char *z,*dest;
|
|
Boolean InHyp=False,InQuot=False;
|
|
|
|
dest=s;
|
|
for (z=s; *z!='\0'; z++)
|
|
BEGIN
|
|
switch (*z)
|
|
BEGIN
|
|
case '\'': if (NOT InQuot) InHyp=NOT InHyp; break;
|
|
case '"': if (NOT InHyp) InQuot=NOT InQuot; break;
|
|
END
|
|
if ((NOT isspace((unsigned char)*z)) OR (InHyp) OR (InQuot)) *(dest++)=(*z);
|
|
END
|
|
*dest='\0';
|
|
END
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* fuehrende Leerzeichen loeschen */
|
|
|
|
void KillPrefBlanks(char *s)
|
|
BEGIN
|
|
char *z=s;
|
|
|
|
while ((*z!='\0') AND (isspace((unsigned char)*z))) z++;
|
|
if (z!=s) strcpy(s,z);
|
|
END
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* anhaengende Leerzeichen loeschen */
|
|
|
|
void KillPostBlanks(char *s)
|
|
BEGIN
|
|
char *z=s+strlen(s)-1;
|
|
|
|
while ((z>=s) AND (isspace((unsigned char)*z))) *(z--)='\0';
|
|
END
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
int strqcmp(const char *s1, const char *s2)
|
|
BEGIN
|
|
int erg=(*s1)-(*s2);
|
|
return (erg!=0) ? erg : strcmp(s1,s2);
|
|
END
|
|
|
|
void strutil_init(void)
|
|
BEGIN
|
|
HexLowerCase=False;
|
|
END
|