1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*0Sstevel@tonic-gate /* All Rights Reserved */ 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate 26*0Sstevel@tonic-gate /* 27*0Sstevel@tonic-gate * Copyright (c) 1999, by Sun Microsystems, Inc. 28*0Sstevel@tonic-gate * All rights reserved. 29*0Sstevel@tonic-gate */ 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*0Sstevel@tonic-gate /*LINTLIBRARY*/ 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate #include "synonyms.h" 35*0Sstevel@tonic-gate #include <sys/types.h> 36*0Sstevel@tonic-gate #include <stdio.h> 37*0Sstevel@tonic-gate #include <ctype.h> 38*0Sstevel@tonic-gate #include "s_string.h" 39*0Sstevel@tonic-gate #include <stdlib.h> 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate /* global to this file */ 42*0Sstevel@tonic-gate #define STRLEN 128UL 43*0Sstevel@tonic-gate #define STRALLOC 128UL 44*0Sstevel@tonic-gate #define MAXINCR 250000UL 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate /* buffer pool for allocating string structures */ 47*0Sstevel@tonic-gate typedef struct { 48*0Sstevel@tonic-gate string s[STRALLOC]; 49*0Sstevel@tonic-gate size_t o; 50*0Sstevel@tonic-gate } stralloc; 51*0Sstevel@tonic-gate static stralloc *freep = NULL; 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate /* pool of freed strings */ 54*0Sstevel@tonic-gate static string *freed = NULL; 55*0Sstevel@tonic-gate static string *s_alloc(void); 56*0Sstevel@tonic-gate static void s_simplegrow(string *, size_t); 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate void 59*0Sstevel@tonic-gate s_free(string *sp) 60*0Sstevel@tonic-gate { 61*0Sstevel@tonic-gate if (sp != NULL) { 62*0Sstevel@tonic-gate sp->ptr = (char *)freed; 63*0Sstevel@tonic-gate freed = sp; 64*0Sstevel@tonic-gate } 65*0Sstevel@tonic-gate } 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate /* allocate a string head */ 68*0Sstevel@tonic-gate static string * 69*0Sstevel@tonic-gate s_alloc(void) 70*0Sstevel@tonic-gate { 71*0Sstevel@tonic-gate if (freep == NULL || freep->o >= STRALLOC) { 72*0Sstevel@tonic-gate freep = (stralloc *)malloc(sizeof (stralloc)); 73*0Sstevel@tonic-gate if (freep == NULL) { 74*0Sstevel@tonic-gate perror("allocating string"); 75*0Sstevel@tonic-gate exit(1); 76*0Sstevel@tonic-gate } 77*0Sstevel@tonic-gate freep->o = (size_t)0; 78*0Sstevel@tonic-gate } 79*0Sstevel@tonic-gate return (&(freep->s[freep->o++])); 80*0Sstevel@tonic-gate } 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate /* create a new `short' string */ 83*0Sstevel@tonic-gate string * 84*0Sstevel@tonic-gate s_new(void) 85*0Sstevel@tonic-gate { 86*0Sstevel@tonic-gate string *sp; 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate if (freed != NULL) { 89*0Sstevel@tonic-gate sp = freed; 90*0Sstevel@tonic-gate /*LINTED*/ 91*0Sstevel@tonic-gate freed = (string *)(freed->ptr); 92*0Sstevel@tonic-gate sp->ptr = sp->base; 93*0Sstevel@tonic-gate return (sp); 94*0Sstevel@tonic-gate } 95*0Sstevel@tonic-gate sp = s_alloc(); 96*0Sstevel@tonic-gate sp->base = sp->ptr = malloc(STRLEN); 97*0Sstevel@tonic-gate if (sp->base == NULL) { 98*0Sstevel@tonic-gate perror("allocating string"); 99*0Sstevel@tonic-gate exit(1); 100*0Sstevel@tonic-gate } 101*0Sstevel@tonic-gate sp->end = sp->base + STRLEN; 102*0Sstevel@tonic-gate s_terminate(sp); 103*0Sstevel@tonic-gate return (sp); 104*0Sstevel@tonic-gate } 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate /* grow a string's allocation by at least `incr' bytes */ 107*0Sstevel@tonic-gate static void 108*0Sstevel@tonic-gate s_simplegrow(string *sp, size_t incr) 109*0Sstevel@tonic-gate { 110*0Sstevel@tonic-gate char *cp; 111*0Sstevel@tonic-gate size_t size; 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate /* 114*0Sstevel@tonic-gate * take a larger increment to avoid mallocing too often 115*0Sstevel@tonic-gate */ 116*0Sstevel@tonic-gate if (((sp->end - sp->base) < incr) && (MAXINCR < incr)) 117*0Sstevel@tonic-gate size = (sp->end - sp->base) + incr; 118*0Sstevel@tonic-gate else if ((sp->end - sp->base) > MAXINCR) 119*0Sstevel@tonic-gate size = (sp->end - sp->base) + MAXINCR; 120*0Sstevel@tonic-gate else 121*0Sstevel@tonic-gate size = (size_t)2 * (sp->end - sp->base); 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate cp = realloc(sp->base, size); 124*0Sstevel@tonic-gate if (cp == NULL) { 125*0Sstevel@tonic-gate perror("string:"); 126*0Sstevel@tonic-gate exit(1); 127*0Sstevel@tonic-gate } 128*0Sstevel@tonic-gate sp->ptr = (sp->ptr - sp->base) + cp; 129*0Sstevel@tonic-gate sp->end = cp + size; 130*0Sstevel@tonic-gate sp->base = cp; 131*0Sstevel@tonic-gate } 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate /* grow a string's allocation */ 134*0Sstevel@tonic-gate int 135*0Sstevel@tonic-gate s_grow(string *sp, int c) 136*0Sstevel@tonic-gate { 137*0Sstevel@tonic-gate s_simplegrow(sp, (size_t)2); 138*0Sstevel@tonic-gate s_putc(sp, c); 139*0Sstevel@tonic-gate return (c); 140*0Sstevel@tonic-gate } 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate /* return a string containing a character array (this had better not grow) */ 143*0Sstevel@tonic-gate string * 144*0Sstevel@tonic-gate s_array(char *cp, size_t len) 145*0Sstevel@tonic-gate { 146*0Sstevel@tonic-gate string *sp = s_alloc(); 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate sp->base = sp->ptr = cp; 149*0Sstevel@tonic-gate sp->end = sp->base + len; 150*0Sstevel@tonic-gate return (sp); 151*0Sstevel@tonic-gate } 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate /* return a string containing a copy of the passed char array */ 154*0Sstevel@tonic-gate string* 155*0Sstevel@tonic-gate s_copy(char *cp) 156*0Sstevel@tonic-gate { 157*0Sstevel@tonic-gate string *sp; 158*0Sstevel@tonic-gate size_t len; 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate sp = s_alloc(); 161*0Sstevel@tonic-gate len = strlen(cp)+1; 162*0Sstevel@tonic-gate sp->base = malloc(len); 163*0Sstevel@tonic-gate if (sp->base == NULL) { 164*0Sstevel@tonic-gate perror("string:"); 165*0Sstevel@tonic-gate exit(1); 166*0Sstevel@tonic-gate } 167*0Sstevel@tonic-gate sp->end = sp->base + len; /* point past end of allocation */ 168*0Sstevel@tonic-gate (void) strcpy(sp->base, cp); 169*0Sstevel@tonic-gate sp->ptr = sp->end - (size_t)1; /* point to NULL terminator */ 170*0Sstevel@tonic-gate return (sp); 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate /* convert string to lower case */ 174*0Sstevel@tonic-gate void 175*0Sstevel@tonic-gate s_tolower(string *sp) 176*0Sstevel@tonic-gate { 177*0Sstevel@tonic-gate char *cp; 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate for (cp = sp->ptr; *cp; cp++) 180*0Sstevel@tonic-gate *cp = tolower(*cp); 181*0Sstevel@tonic-gate } 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate void 184*0Sstevel@tonic-gate s_skipwhite(string *sp) 185*0Sstevel@tonic-gate { 186*0Sstevel@tonic-gate while (isspace(*sp->ptr)) 187*0Sstevel@tonic-gate s_skipc(sp); 188*0Sstevel@tonic-gate } 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate /* append a char array to a string */ 191*0Sstevel@tonic-gate string * 192*0Sstevel@tonic-gate s_append(string *to, char *from) 193*0Sstevel@tonic-gate { 194*0Sstevel@tonic-gate if (to == NULL) 195*0Sstevel@tonic-gate to = s_new(); 196*0Sstevel@tonic-gate if (from == NULL) 197*0Sstevel@tonic-gate return (to); 198*0Sstevel@tonic-gate for (; *from; from++) 199*0Sstevel@tonic-gate s_putc(to, (int)(unsigned int)*from); 200*0Sstevel@tonic-gate s_terminate(to); 201*0Sstevel@tonic-gate return (to); 202*0Sstevel@tonic-gate } 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate /* 205*0Sstevel@tonic-gate * Append a logical input sequence into a string. Ignore blank and 206*0Sstevel@tonic-gate * comment lines. Backslash preceding newline indicates continuation. 207*0Sstevel@tonic-gate * The `lineortoken' variable indicates whether the sequence to beinput 208*0Sstevel@tonic-gate * is a whitespace delimited token or a whole line. 209*0Sstevel@tonic-gate * 210*0Sstevel@tonic-gate * FILE *fp; stream to read from 211*0Sstevel@tonic-gate * string *to; where to put token 212*0Sstevel@tonic-gate * int lineortoken; how the sequence terminates 213*0Sstevel@tonic-gate * 214*0Sstevel@tonic-gate * Returns a pointer to the string or NULL. Trailing newline is stripped off. 215*0Sstevel@tonic-gate */ 216*0Sstevel@tonic-gate string * 217*0Sstevel@tonic-gate s_seq_read(FILE *fp, string *to, int lineortoken) 218*0Sstevel@tonic-gate { 219*0Sstevel@tonic-gate int c; 220*0Sstevel@tonic-gate int done = 0; 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate if (feof(fp)) 223*0Sstevel@tonic-gate return (NULL); 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate /* get rid of leading goo */ 226*0Sstevel@tonic-gate do { 227*0Sstevel@tonic-gate c = getc(fp); 228*0Sstevel@tonic-gate switch (c) { 229*0Sstevel@tonic-gate case EOF: 230*0Sstevel@tonic-gate if (to != NULL) 231*0Sstevel@tonic-gate s_terminate(to); 232*0Sstevel@tonic-gate return (NULL); 233*0Sstevel@tonic-gate case '#': 234*0Sstevel@tonic-gate /*LINTED*/ 235*0Sstevel@tonic-gate while ((c = getc(fp)) != '\n' && c != EOF); 236*0Sstevel@tonic-gate break; 237*0Sstevel@tonic-gate case ' ': 238*0Sstevel@tonic-gate case '\t': 239*0Sstevel@tonic-gate case '\n': 240*0Sstevel@tonic-gate case '\r': 241*0Sstevel@tonic-gate case '\f': 242*0Sstevel@tonic-gate break; 243*0Sstevel@tonic-gate default: 244*0Sstevel@tonic-gate done = 1; 245*0Sstevel@tonic-gate break; 246*0Sstevel@tonic-gate } 247*0Sstevel@tonic-gate } while (!done); 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate if (to == NULL) 250*0Sstevel@tonic-gate to = s_new(); 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate /* gather up a sequence */ 253*0Sstevel@tonic-gate for (;;) { 254*0Sstevel@tonic-gate switch (c) { 255*0Sstevel@tonic-gate case '\\': 256*0Sstevel@tonic-gate c = getc(fp); 257*0Sstevel@tonic-gate if (c != '\n') { 258*0Sstevel@tonic-gate s_putc(to, (int)(unsigned int)'\\'); 259*0Sstevel@tonic-gate s_putc(to, c); 260*0Sstevel@tonic-gate } 261*0Sstevel@tonic-gate break; 262*0Sstevel@tonic-gate case EOF: 263*0Sstevel@tonic-gate case '\r': 264*0Sstevel@tonic-gate case '\f': 265*0Sstevel@tonic-gate case '\n': 266*0Sstevel@tonic-gate s_terminate(to); 267*0Sstevel@tonic-gate return (to); 268*0Sstevel@tonic-gate case ' ': 269*0Sstevel@tonic-gate case '\t': 270*0Sstevel@tonic-gate if (lineortoken == TOKEN) { 271*0Sstevel@tonic-gate s_terminate(to); 272*0Sstevel@tonic-gate return (to); 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate /* fall through */ 275*0Sstevel@tonic-gate default: 276*0Sstevel@tonic-gate s_putc(to, c); 277*0Sstevel@tonic-gate break; 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate c = getc(fp); 280*0Sstevel@tonic-gate } 281*0Sstevel@tonic-gate } 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate string * 284*0Sstevel@tonic-gate s_tok(string *from, char *split) 285*0Sstevel@tonic-gate { 286*0Sstevel@tonic-gate char *splitend = strpbrk(from->ptr, split); 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate if (splitend) { 289*0Sstevel@tonic-gate string *to = s_new(); 290*0Sstevel@tonic-gate for (; from->ptr < splitend; ) { 291*0Sstevel@tonic-gate s_putc(to, (int)(unsigned int)*from->ptr); 292*0Sstevel@tonic-gate from->ptr++; 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate s_terminate(to); 295*0Sstevel@tonic-gate s_restart(to); 296*0Sstevel@tonic-gate /* LINT: warning due to lint bug */ 297*0Sstevel@tonic-gate from->ptr += strspn(from->ptr, split); 298*0Sstevel@tonic-gate return (to); 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate else if (from->ptr[0]) { 302*0Sstevel@tonic-gate string *to = s_clone(from); 303*0Sstevel@tonic-gate while (*from->ptr) 304*0Sstevel@tonic-gate from->ptr++; 305*0Sstevel@tonic-gate return (to); 306*0Sstevel@tonic-gate } 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate else 309*0Sstevel@tonic-gate return (NULL); 310*0Sstevel@tonic-gate } 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate /* 313*0Sstevel@tonic-gate * Append an input line to a string. 314*0Sstevel@tonic-gate * 315*0Sstevel@tonic-gate * Returns a pointer to the string (or NULL). 316*0Sstevel@tonic-gate * Trailing newline is left on. 317*0Sstevel@tonic-gate */ 318*0Sstevel@tonic-gate char * 319*0Sstevel@tonic-gate s_read_line(FILE *fp, string *to) 320*0Sstevel@tonic-gate { 321*0Sstevel@tonic-gate int c; 322*0Sstevel@tonic-gate size_t len = 0; 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate s_terminate(to); 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate /* end of input */ 327*0Sstevel@tonic-gate if (feof(fp) || (c = getc(fp)) == EOF) 328*0Sstevel@tonic-gate return (NULL); 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate /* gather up a line */ 331*0Sstevel@tonic-gate for (; ; ) { 332*0Sstevel@tonic-gate len++; 333*0Sstevel@tonic-gate switch (c) { 334*0Sstevel@tonic-gate case EOF: 335*0Sstevel@tonic-gate s_terminate(to); 336*0Sstevel@tonic-gate return (to->ptr - len); 337*0Sstevel@tonic-gate case '\n': 338*0Sstevel@tonic-gate s_putc(to, (int)(unsigned int)'\n'); 339*0Sstevel@tonic-gate s_terminate(to); 340*0Sstevel@tonic-gate return (to->ptr - len); 341*0Sstevel@tonic-gate default: 342*0Sstevel@tonic-gate s_putc(to, c); 343*0Sstevel@tonic-gate break; 344*0Sstevel@tonic-gate } 345*0Sstevel@tonic-gate c = getc(fp); 346*0Sstevel@tonic-gate } 347*0Sstevel@tonic-gate } 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate /* 350*0Sstevel@tonic-gate * Read till eof 351*0Sstevel@tonic-gate */ 352*0Sstevel@tonic-gate size_t 353*0Sstevel@tonic-gate s_read_to_eof(FILE *fp, string *to) 354*0Sstevel@tonic-gate { 355*0Sstevel@tonic-gate size_t got; 356*0Sstevel@tonic-gate size_t have; 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate s_terminate(to); 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate for (; ; ) { 361*0Sstevel@tonic-gate if (feof(fp)) 362*0Sstevel@tonic-gate break; 363*0Sstevel@tonic-gate /* allocate room for a full buffer */ 364*0Sstevel@tonic-gate have = to->end - to->ptr; 365*0Sstevel@tonic-gate if (have < 4096UL) 366*0Sstevel@tonic-gate s_simplegrow(to, (size_t)4096); 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate /* get a buffers worth */ 369*0Sstevel@tonic-gate have = to->end - to->ptr; 370*0Sstevel@tonic-gate got = fread(to->ptr, (size_t)1, have, fp); 371*0Sstevel@tonic-gate if (got == (size_t)0) 372*0Sstevel@tonic-gate break; 373*0Sstevel@tonic-gate /* LINT: warning due to lint bug */ 374*0Sstevel@tonic-gate to->ptr += got; 375*0Sstevel@tonic-gate } 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate /* null terminate the line */ 378*0Sstevel@tonic-gate s_terminate(to); 379*0Sstevel@tonic-gate return (to->ptr - to->base); 380*0Sstevel@tonic-gate } 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate /* 383*0Sstevel@tonic-gate * Get the next field from a string. The field is delimited by white space, 384*0Sstevel@tonic-gate * single or double quotes. 385*0Sstevel@tonic-gate * 386*0Sstevel@tonic-gate * string *from; string to parse 387*0Sstevel@tonic-gate * string *to; where to put parsed token 388*0Sstevel@tonic-gate */ 389*0Sstevel@tonic-gate string * 390*0Sstevel@tonic-gate s_parse(string *from, string *to) 391*0Sstevel@tonic-gate { 392*0Sstevel@tonic-gate while (isspace(*from->ptr)) 393*0Sstevel@tonic-gate from->ptr++; 394*0Sstevel@tonic-gate if (*from->ptr == '\0') 395*0Sstevel@tonic-gate return (NULL); 396*0Sstevel@tonic-gate if (to == NULL) 397*0Sstevel@tonic-gate to = s_new(); 398*0Sstevel@tonic-gate if (*from->ptr == '\'') { 399*0Sstevel@tonic-gate from->ptr++; 400*0Sstevel@tonic-gate for (; *from->ptr != '\'' && *from->ptr != '\0'; from->ptr++) 401*0Sstevel@tonic-gate s_putc(to, (int)(unsigned int)*from->ptr); 402*0Sstevel@tonic-gate if (*from->ptr == '\'') 403*0Sstevel@tonic-gate from->ptr++; 404*0Sstevel@tonic-gate } else if (*from->ptr == '"') { 405*0Sstevel@tonic-gate from->ptr++; 406*0Sstevel@tonic-gate for (; *from->ptr != '"' && *from->ptr != '\0'; from->ptr++) 407*0Sstevel@tonic-gate s_putc(to, (int)(unsigned int)*from->ptr); 408*0Sstevel@tonic-gate if (*from->ptr == '"') 409*0Sstevel@tonic-gate from->ptr++; 410*0Sstevel@tonic-gate } else { 411*0Sstevel@tonic-gate for (; !isspace(*from->ptr) && *from->ptr != '\0'; from->ptr++) 412*0Sstevel@tonic-gate s_putc(to, (int)(unsigned int)*from->ptr); 413*0Sstevel@tonic-gate } 414*0Sstevel@tonic-gate s_terminate(to); 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate return (to); 417*0Sstevel@tonic-gate } 418