DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T s

⟦e935732b1⟧ TextFile

    Length: 9099 (0x238b)
    Types: TextFile
    Names: »stringfunc.c,v«

Derivation

└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89
    └─⟦34cc4e2f7⟧ »./UNRELEASED/xgdb3.2.tar.Z« 
        └─⟦80fac5d7c⟧ 
            └─⟦this⟧ »./RCS/stringfunc.c,v« 

TextFile

head     1.1;
access   ;
symbols  ;
locks    hubbard:1.1; strict;
comment  @ * @;


1.1
date     89.07.05.15.36.42;  author hubbard;  state Exp;
branches ;
next     ;


desc
@Initial checkin, Beta version 0.1.
@



1.1
log
@Initial revision
@
text
@\f


#ifndef lint
static char rcsid[] = "$Header$";
#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$
 * 
 */

#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';
}
@