Files
Arquivotheca.AIX-4.1.3/bldenv/make/str.c
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

644 lines
14 KiB
C

/*
* COMPONENT_NAME: BLDPROCESS
*
* FUNCTIONS: Str_Match
* _string_headtail
* _string_prefsuff
* brk_string
* string_archmemb
* string_concat
* string_create
* string_deref
* string_finish
* string_flatten
* string_init
* string_ref
* string_setup
* strndup
*
* ORIGINS: 27,71
*
* This module contains IBM CONFIDENTIAL code. -- (IBM
* Confidential Restricted when combined with the aggregated
* modules for this product)
* SOURCE MATERIALS
*
* (C) COPYRIGHT International Business Machines Corp. 1994
* All Rights Reserved
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
/*
* @OSF_FREE_COPYRIGHT@
* COPYRIGHT NOTICE
* Copyright (c) 1992, 1991, 1990
* Open Software Foundation, Inc.
*
* Permission is hereby granted to use, copy, modify and freely distribute
* the software in this file and its documentation for any purpose without
* fee, provided that the above copyright notice appears in all copies and
* that both the copyright notice and this permission notice appear in
* supporting documentation. Further, provided that the name of Open
* Software Foundation, Inc. ("OSF") not be used in advertising or
* publicity pertaining to distribution of the software without prior
* written permission from OSF. OSF makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/
/*
* HISTORY
* $Log: str.c,v $
* Revision 1.2.2.8 1992/12/03 19:07:19 damon
* ODE 2.2 CR 346. Expanded copyright
* [1992/12/03 18:36:34 damon]
*
* Revision 1.2.2.7 1992/11/13 15:19:56 root
* Changed assignment of NULL to '\0'
* [1992/11/13 14:57:58 root]
*
* Revision 1.2.2.6 1992/09/24 19:27:12 gm
* CR286: Major improvements to make internals.
* [1992/09/24 17:55:40 gm]
*
* Revision 1.2.2.5 1992/06/24 16:41:54 damon
* CR 60. brk_string now counts args correctly
* [1992/06/24 16:38:41 damon]
*
* Revision 1.2.2.4 1992/06/16 21:24:36 damon
* 2.1.1 touch-up
* [1992/06/16 21:18:22 damon]
*
* Revision 1.2.2.3 1992/06/12 00:49:18 damon
* Synched with 2.1.1
* [1992/06/12 00:38:50 damon]
*
* Revision 1.2.4.3 1992/03/25 22:46:03 damon
* Removed comment after endif
* [1992/03/25 21:49:50 damon]
*
* Revision 1.2.4.2 1992/03/09 21:10:41 mhickey
* Closed open comment in brk_string that was preventing
* leading whitespace from being stripped from command lines.
* [1992/03/09 21:01:44 mhickey]
*
* Revision 1.2 1991/12/05 20:45:15 devrcs
* Changes for Reno make
* [91/03/22 16:10:27 mckeen]
*
* $EndLog$
*/
/*-
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
* Copyright (c) 1988, 1989 by Adam de Boor
* Copyright (c) 1989 by Berkeley Softworks
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
static char sccsid[] = "@(#)52 1.4 src/bldenv/make/str.c, bldprocess, bos412, GOLDA411a 1/19/94 16:31:37";
#endif /* not lint */
#ifndef lint
static char rcsid[] = "@(#)str.c 5.8 (Berkeley) 6/1/90";
#endif
/* not lint */
#include "make.h"
#include "hash.h"
Hash_Table stringHashTable;
/*-
* strndup --
* allocate and return a copy of the string s of length n.
*
* returns --
* the resulting string in allocated space.
*/
char *
strndup(const char *s, int n)
{
char *r = (char *)malloc(n+1);
if (r == NULL)
enomem();
memcpy(r, s, n);
r[n] = '\0';
return(r);
}
/*-
* string_concat --
* concatenate the two strings, inserting a space or slash between them,
* freeing them if requested.
*
* returns --
* the resulting string in allocated space.
*/
string_t
string_concat(string_t s1, string_t s2, int flags)
{
register int len1, len2;
register char *result;
string_t rs;
/* get the length of both strings */
len1 = s1 ? s1->len : 0;
len2 = s2 ? s2->len : 0;
/* allocate length plus separator plus EOS */
result = emalloc((u_int)(len1 + len2 + 2));
/* copy first string into place */
if (len1)
memcpy(result, s1->data, len1);
if (len1 && len2) {
/* add separator character */
if (flags & STR_ADDSPACE) {
result[len1] = ' ';
++len1;
} else if (flags & STR_ADDSLASH) {
result[len1] = '/';
++len1;
}
}
/* copy second string into place */
if (len2)
memcpy(result + len1, s2->data, len2);
result[len1+len2] = '\0';
rs = string_create(result);
/* free original strings */
free(result);
if (flags & STR_DOFREE) {
string_deref(s1);
string_deref(s2);
}
return(rs);
}
/*-
* brk_string --
* Fracture a string into an array of words (as delineated by tabs or
* spaces) taking quotation marks into account. Leading tabs/spaces
* are ignored.
*
* returns --
* Pointer to the array of pointers to the words. To make life easier,
* the first word is always the value of the MAKE variable.
*/
char **
brk_string(register char *str, int *store_argc)
{
static int argmax, curlen;
static const char **argv;
static char *buf;
register int argc, ch;
register char inquote, *p, *start, *t;
int len;
/* save off pmake variable */
if (!argv) {
argv = (const char **)emalloc((argmax = 50) * sizeof(char *));
argv[0] = Var_Value(sMAKE, VAR_GLOBAL);
}
/* skip leading space chars. */
for (; *str == ' ' || *str == '\t'; ++str);
/* allocate room for a copy of the string */
if ((len = strlen(str) + 1) > curlen)
buf = emalloc(curlen = len);
/*
* copy the string; at the same time, parse backslashes,
* quotes and build the argument list.
*/
argc = 1;
inquote = '\0';
for (p = str, start = t = buf;; ++p) {
switch(ch = *p) {
case '"':
case '\'':
if (inquote)
if (inquote == ch)
inquote = '\0';
else
break;
else
inquote = ch;
continue;
case ' ':
case '\t':
if (inquote)
break;
for (; *p == ' ' || *p == '\t'; ++p);
ch = *p--;
if (!start)
continue;
/* FALLTHROUGH */
case '\n':
case '\0':
/*
* end of a token -- make sure there's enough argv
* space and save off a pointer.
*/
*t++ = '\0';
if (argc == argmax) {
argmax *= 2; /* ramp up fast */
if (!(argv = (const char **)realloc(argv,
argmax * sizeof(char *))))
enomem();
}
argv[argc++] = start;
start = (char *)NULL;
if (ch == '\n' || ch == '\0')
goto done;
continue;
case '\\':
switch (ch = *++p) {
case '\0':
case '\n':
/* hmmm; fix it up as best we can */
ch = '\\';
--p;
break;
case 'b':
ch = '\b';
break;
case 'f':
ch = '\f';
break;
case 'n':
ch = '\n';
break;
case 'r':
ch = '\r';
break;
case 't':
ch = '\t';
break;
}
break;
}
if (!start)
start = t;
*t++ = ch;
}
done: argv[argc] = (char *)NULL;
*store_argc = argc;
return((char **)argv);
}
/*
* Str_Match --
*
* See if a particular string matches a particular pattern.
*
* Results: Non-zero is returned if string matches pattern, 0 otherwise. The
* matching operation permits the following special characters in the
* pattern: *?\[] (see the man page for details on what these mean).
*
* Side effects: None.
*/
int
Str_Match(
register const char *string, /* String */
register const char *pattern) /* Pattern */
{
int c2;
for (;;) {
/*
* See if we're at the end of both the pattern and the
* string. If, we succeeded. If we're at the end of the
* pattern but not at the end of the string, we failed.
*/
if (*pattern == 0)
return(!*string);
if (*string == 0 && *pattern != '*')
return(0);
/*
* Check for a "*" as the next pattern character. It matches
* any substring. We handle this by calling ourselves
* recursively for each postfix of string, until either we
* match or we reach the end of the string.
*/
if (*pattern == '*') {
pattern += 1;
if (*pattern == 0)
return(1);
while (*string != 0) {
if (Str_Match(string, pattern))
return(1);
++string;
}
return(0);
}
/*
* Check for a "?" as the next pattern character. It matches
* any single character.
*/
if (*pattern == '?')
goto thisCharOK;
/*
* Check for a "[" as the next pattern character. It is
* followed by a list of characters that are acceptable, or
* by a range (two characters separated by "-").
*/
if (*pattern == '[') {
++pattern;
for (;;) {
if ((*pattern == ']') || (*pattern == 0))
return(0);
if (*pattern == *string)
break;
if (pattern[1] == '-') {
c2 = pattern[2];
if (c2 == 0)
return(0);
if ((*pattern <= *string) &&
(c2 >= *string))
break;
if ((*pattern >= *string) &&
(c2 <= *string))
break;
pattern += 2;
}
++pattern;
}
while ((*pattern != ']') && (*pattern != 0))
++pattern;
goto thisCharOK;
}
/*
* If the next pattern character is '/', just strip off the
* '/' so we do exact matching on the character that follows.
*/
if (*pattern == '\\') {
++pattern;
if (*pattern == 0)
return(0);
}
/*
* There's no special character. Just make sure that the
* next characters of each string match.
*/
if (*pattern != *string)
return(0);
thisCharOK: ++pattern;
++string;
}
}
/*-
* string_flatten - Flatten out a pathname
*/
string_t
string_flatten(string_t spath)
{
register char *p, *q, *r;
register char **sp, **tp;
char *stack[64];
char *path = strdup(spath->data);
string_t result;
p = q = path;
sp = tp = stack;
if (*q == '/') {
p++;
while (*++q == '/')
;
}
for (r = q; *r; r = q) {
while (*++q && *q != '/')
;
if (q != r+1 || *r != '.') {
if (q != r+2 || *r != '.' || *(r+1) != '.')
*sp++ = r;
else if (sp != tp)
sp--;
else {
*p++ = '.';
*p++ = '.';
if (*q)
*p++ = '/';
}
}
while (*q == '/')
q++;
}
while (tp < sp)
for (q = *tp++; *q; )
if ((*p++ = *q++) == '/')
break;
if (p > path+1 && *(p-1) == '/')
--p;
*p = 0;
result = string_create(path);
string_deref(spath);
return(result);
}
string_t
string_ref(string_t s)
{
if (s->_refCount == 0)
printf("string %s had zero refs\n", s->data);
else if (s->_refCount < 0) {
printf("string %s had negative refs\n", s->data);
s->_refCount = 0;
}
s->_refCount += 1;
return s;
}
void
string_deref(string_t s)
{
register Hash_Entry *he;
s->_refCount -= 1;
if (s->_refCount == 0) {
if (s->_flags & STR_HEADTAIL) {
string_deref(s->_head);
string_deref(s->_tail);
}
if (s->_flags & STR_PREFSUFF) {
string_deref(s->_pref);
string_deref(s->_suff);
}
if (s->_arch)
string_deref(s->_arch);
if (s->_memb)
string_deref(s->_memb);
he = Hash_FindEntry(&stringHashTable, s);
Hash_DeleteEntry(&stringHashTable, he);
free((void *)s->data);
free(s);
} else if (s->_refCount < 0)
printf("string %s negative refs\n", s->data);
}
static void
string_setup(string_t s)
{
register unsigned h;
register const char *p;
h = 0;
for (p = s->data; *p; p++)
h = (h << 5) - h + *p;
s->hashval = h;
s->len = p - s->data;
}
static void
string_finish(string_t s)
{
register const char *cp, *p, *tail, *suff;
register int f;
f = 0;
cp = s->data;
tail = NULL;
suff = NULL;
p = cp + s->len;
while (p > cp) {
p--;
if (*p == '/') {
tail = p + 1;
break;
}
if (suff == NULL && *p == '.') {
suff = p;
continue;
}
if (*p == '$')
f |= STR_HASVAR;
}
if (f == 0 && *cp == '$')
f |= STR_HASVAR;
else
while (f == 0 && p > cp)
if (*--p == '$')
f |= STR_HASVAR;
s->_flags = f;
s->_tail = (string_t) tail;
s->_pref = (string_t) (tail ? tail : cp);
s->_suff = (string_t) suff;
}
string_t
string_create(const char *cp)
{
struct string strtmpl;
static struct string strzero;
string_t s;
strtmpl = strzero;
strtmpl.data = cp;
string_setup(&strtmpl);
s = Hash_FindString(&stringHashTable, &strtmpl);
if (s != (string_t) NULL)
return(string_ref(s));
s = (string_t) malloc(sizeof(struct string));
if (s == NULL)
enomem();
*s = strtmpl;
s->data = (const char *)strndup(cp, s->len);
string_finish(s);
s->_refCount = 1;
Hash_CreateString(&stringHashTable, s);
return(s);
}
void
string_init(void)
{
Hash_InitTable(&stringHashTable, 1024);
}
void
_string_headtail(string_t s)
{
const char *cp = s->data;
const char *p;
p = (const char *) s->_tail;
if (p == NULL) {
s->_head = (string_t) NULL;
s->_tail = string_ref(s);
} else {
s->_tail = string_create(p--);
if (p == cp && *(p + 1) == '\0')
s->_head = string_ref(s);
else if (p == cp)
s->_head = string_create("/");
else {
p = (const char *)strndup(cp, p - cp);
s->_head = string_create(p);
free((char *)p);
}
}
s->_flags |= STR_HEADTAIL;
}
void
_string_prefsuff(string_t s)
{
const char *cp, *p;
cp = (const char *) s->_pref;
p = (const char *) s->_suff;
if (p == NULL ||
(*p == '\0' &&
(p == cp + 1 ||
(p == cp + 2 && *(p-2) == '.')))) {
s->_pref = string_create((const char *) s->_pref);
s->_suff = (string_t) NULL;
} else {
if (p == cp) {
s->_suff = string_ref(s);
s->_pref = string_ref(sNULL);
} else {
s->_suff = string_create(p);
p = (const char *)strndup(cp, p - cp);
s->_pref = string_create(p);
free((char *)p);
}
}
s->_flags |= STR_PREFSUFF;
}
void
string_archmemb(string_t s, string_t arch, string_t memb)
{
s->_arch = string_ref(arch);
s->_memb = string_ref(memb);
}