|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 8985 (0x2319)
Types: TextFile
Names: »stringfunc.c«
└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89
└─⟦e10a7c8ba⟧ »./UNRELEASED/xgdb.tar.Z«
└─⟦ae30648b5⟧
└─⟦this⟧ »./stringfunc.c«
\f
#ifndef lint
static char rcsid[] = "$Header: stringfunc.c,v 1.1 89/07/05 15:36:42 hubbard Exp $";
#endif
/*
*
* Copyright 1988, 1989
* PCS Computer Systeme, GmbH
* Munich, West Germany
*
* All rights reserved.
*
* This is unsupported software and is subject to change without notice.
* PCS makes no representations about the suitability of this software
* for any purpose. It is supplied "as is" without express or implied
* warranty.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of PCS Computer Systeme not be used in
* advertising or publicity pertaining to distribution of the software
* without specific, written prior permission.
*
*/
/*
* Author: Jordan K. Hubbard
* For: PCS Computer Systems, GmbH.
* When: February 10th, 1989.
*
* $Log: stringfunc.c,v $
* Revision 1.1 89/07/05 15:36:42 hubbard
* Initial revision
*
*
*/
#include "xgdb.h"
#include <ctype.h>
/*
* Various silly string utilities..
*/
/*
* Given a string, return everything up to the first newline or the end.
*/
String oneLine(s)
String s;
{
static char line[256];
int i = 0;
Entry("oneLine");
if (!s) {
Leave(NULL);
}
while (s && s[i] != '\n' && i < 255) {
line[i] = s[i];
i++;
}
line[i] = '\0';
Leave(line);
}
/*
* Given a path name, return just the file name with all preceeding directory
* components stripped off.
*/
String strip_directory_prefix(s)
String s;
{
Cardinal n;
Entry("strip_directory_prefix");
if (!s) {
Leave(s);
}
n = strlen(s);
while (n) {
if (s[n] == '/')
break;
n--;
}
Leave((s + (n ? n + 1 : 0)));
}
/*
* Given a path name, return the directory components sans filename.
* (counterpart to above).
*/
String strip_file_component(s)
String s;
{
int len;
char target[MAXPATHLEN];
Entry("strip_file_component");
if (!s || !strlen(s)) {
Leave(NULL);
}
len = strlen(s);
while (len && s[len] != '/')
len--;
if (len) {
CPYN(target, s, len);
Leave(target);
}
else
Leave(s);
}
#define upper(c) if (c >= 'a' && c <= 'z') c -= 32
/*
* Kludge, but close enough by government standards. Tries to derive
* a class name from an application name.
*/
String class_from_name(s)
String s;
{
static char name[50];
Entry("class_from_name");
if (s && strlen(s) > 1) {
strcpy(name, s);
upper(name[0]);
upper(name[1]);
Leave(name);
}
else
Leave(s);
}
/*
* Removes characters from "s" that fall into the range between s1 and
* s2. Returns the number of characters clipped.
*/
int clipString(s, s1, s2)
String s;
int s1, s2;
{
int len;
Entry("clipString");
ASSERT(NULLP(s));
len = strlen(s);
if (s2 >= len) {
s[s1] = '\0';
Leave(len - s1);
}
else {
bcopy(s + s2, s + s1, len - s2);
s[len - (s2 - s1)] = '\0';
Leave(s2 - s1);
}
}
/*
* Insert "len" characters from src into dest, starting at destlen. If
* srclen + destlen > maxlen, roll off some characters, breaking at line
* boundries if possible.
*/
int insertString(dest, destlen, maxlen, src, srclen)
String dest, src;
int destlen, maxlen, srclen;
{
int rolloff = 0;
Entry("insertString");
ASSERT(NULLP(src) || NULLP(dest));
if (destlen + srclen > maxlen) {
rolloff = (destlen + srclen) - maxlen;
for (i = 0; i < destlen; i++) {
if (dest[i] == '\n' && i >= rolloff) {
rolloff = i + 1;
break;
}
}
destlen -= rolloff;
bcopy(dest + rolloff, dest, destlen);
}
bcopy(src, dest + destlen, srclen);
Leave(srclen + destlen);
}
/*
* Convert number to string.
*/
String itoa(i)
int i;
{
static char ret[32];
Entry("itoa");
sprintf(ret, "%d", i);
Leave(ret);
}
/*
* Do various rude things to a string, like expand tabs and
* make control characters visible.
* The expanded string is static storage and should be copied if
* you want to save it across subsequent calls.
* Strings expanding to more than MAX_EXPAND bytes are truncated.
*
* If map_newlines is set, newlines are presumed to be evil for some reason
* and are mapped to this character.
*/
#define MAX_EXPAND 2500
String expand_string(s, map_newlines)
register String s;
char map_newlines;
{
register int i = 0, i2 = 0, col = 0;
int len;
static char tmp[MAX_EXPAND];
Entry("expand_string");
ASSERT(NULLP(s));
len = strlen(s);
while (i < len && i2 < MAX_EXPAND) {
if (isprint(s[i])) {
tmp[i2++] = s[i];
col++;
}
else if (s[i] == '\t') {
int tb = 4 - (col % 4), i3;
for (i3 = 0; i3 < tb; i3++) {
tmp[i2++] = ' ';
col++;
}
}
else if (s[i] == '\n') {
if (!map_newlines)
tmp[i2++] = s[i];
else
tmp[i2++] = map_newlines;
col = 0;
}
else {
tmp[i2++] = '^';
tmp[i2++] = s[i] + 64;
col += 2;
}
i++;
}
tmp[i2] = '\0';
Leave(tmp);
}
/*
* Return span of string from p1 to p2, null terminating the
* result. String spans > MAXSTR chars are trunctated. String
* span is static storage and should be copied if you want to save
* it across subsequent calls.
*/
#define MAXSTR 512
String substr(s, p1, p2)
register String s;
register int p1, p2;
{
static char ret[MAXSTR];
register int i = 0;
Entry("substr");
ASSERT(NULLP(s));
if (p1 > p2) {
puke("%p: start %d, end %d. start must be <= end",
p1, p2);
Leave(NULL);
}
if (p2 - p1 > MAXSTR) {
puke("%p: end - start is > max len of %d", MAXSTR);
Leave(NULL);
}
while (p1 <= p2)
ret[i++] = s[p1++];
ret[i] = '\0';
Leave(ret);
}
/*
* Concatenate two strings into static area, returning pointer to
* result.
*/
String strconcat(s1, s2)
register String s1, s2;
{
static char ret[MAXSTR];
Entry("strconcat");
strcpy(ret, s1);
strcat(ret, s2);
Leave(ret);
}
/*
* Return integer subscript of character 'c' in string 's'.
* (why doesn't this already exist in Unix?).
*/
int iindex(s, c)
register char *s, c;
{
register char *cp;
Entry("iindex");
if (NULLP(s))
Leave(-1);
cp = index(s, c);
if (cp) {
Leave(cp - s);
}
else {
Leave(-1);
}
}
#define DIGIT(x) (isdigit(x) ? (x) - '0' : \
islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
/*
* Convert backslash notation to control characters, in place.
* We can do this in place since the converted string will always smaller
* than the original.
*
* Code grubbed from something by Jef Poskanzer (PD printf()), though
* the parsing of numeric constants has been re-done.
*/
void ctrl(s)
register String s;
{
register String op = s;
register Cardinal c;
unsigned int base = 0;
int value = 0;
ASSERT(NULLP(s));
while ((c = *s) != 0) {
if (base == 0 && c != '\\') {
*op = c;
op++;
s++;
continue;
}
else if (c == '\\')
s++;
switch (*s) {
case '\0': /* end-of-string: user goofed */
s--;
break;
case 'n': /* newline */
*op++ = '\n';
break;
case 's': /* space */
*op++ = ' ';
break;
case 't': /* horizontal tab */
*op++ = '\t';
break;
case 'r': /* carriage-return */
*op++ = '\r';
break;
case 'f': /* form-feed */
*op++ = '\f';
break;
case 'b': /* backspace */
*op++ = '\b';
break;
case 'v': /* vertical tab */
*op++ = '\13';
break;
/* A number. Hmmm. Might be octal, might be hex, might be decimal. */
case '0':
if (base == 0) {
if (s[1] == 'x' || s[1] == 'X') /* 0x.. is hex */
base = 16;
else
base = 8; /* 0xxx is octal */
value = 0;
}
case '1': case '2': case '3':
case '4': case '5': case '6':
case '7': case '8': case '9':
/* First time through means decimal */
if (base == 0) {
base = 10;
value = 0;
}
value = base * value - DIGIT(*s);
if (!isdigit(s[1])) { /* that was the last number */
*op++ = abs(value);
base = 0;
}
break;
case 'X':
case 'x':
if (base != 16) /* not part of hex constant, back up */
s--;
break;
case '&': /* special zero-width `character' */
break;
default:
*op++ = *s;
}
s++;
}
*op = '\0';
}