1 /* @(#)misc.c	1.4 19/01/07 Copyright 2017-2019 J. Schilling */
2 #include <schily/mconfig.h>
3 /*
4  *	Functions for using the printf Bourne Shell builtin as standalone
5  *
6  *	Copyright (c) 2017-2019 J. Schilling
7  */
8 /*
9  * The contents of this file are subject to the terms of the
10  * Common Development and Distribution License, Version 1.0 only
11  * (the "License").  You may not use this file except in compliance
12  * with the License.
13  *
14  * See the file CDDL.Schily.txt in this distribution for details.
15  * A copy of the CDDL is also available via the Internet at
16  * http://www.opensource.org/licenses/cddl1.txt
17  *
18  * When distributing Covered Code, include this CDDL HEADER in each
19  * file and include the License file CDDL.Schily.txt from this distribution.
20  */
21 
22 static	UConst char sccsid[] =
23 	"@(#)misc.c	1.4 19/01/07 Copyright 2017-2019 J. Schilling";
24 
25 #include "defs.h"
26 
27 int	exitval;
28 
29 unsigned char *
escape_char(cp,res,echomode)30 escape_char(cp, res, echomode)
31 	unsigned char	*cp;
32 	unsigned char	*res;
33 	int		echomode;	/* echo mode vs. C mode */
34 {
35 	int		j;
36 	int		wd;
37 	unsigned char	c;
38 
39 	switch (*++cp) {
40 #if	defined(DO_SYSPRINTF) || defined(DO_ECHO_A)
41 	case 'a':	c = ALERT; break;
42 #endif
43 	case 'b':	c = '\b'; break;
44 	case 'c':	if (echomode)
45 				return (NULL);
46 			goto norm;
47 	case 'f':	c = '\f'; break;
48 	case 'n':	c = '\n'; break;
49 	case 'r':	c = '\r'; break;
50 	case 't':	c = '\t'; break;
51 	case 'v':	c = '\v'; break;
52 	case '\\':	c = '\\'; break;
53 
54 	case '0':
55 		j = wd = 0;
56 		if (!echomode)		/* '\0123' must be '\n3' */
57 			j = 1;
58 	oct:
59 		while ((*++cp >= '0' &&
60 		    *cp <= '7') && j++ < 3) {
61 			wd <<= 3;
62 			wd |= (*cp - '0');
63 		}
64 		c = wd;
65 		--cp;
66 		break;
67 
68 	case '1': case '2': case '3': case '4':
69 	case '5': case '6': case '7':
70 		if (!echomode) {
71 			j = 1;
72 			wd = (*cp - '0');
73 			goto oct;
74 		}
75 		/* FALLTHRU */
76 	default:
77 	norm:
78 		c = *--cp;
79 	}
80 	*res = c;
81 	return (cp);
82 }
83 
84 #undef	BRKINCR
85 #define	BRKINCR 1024
86 
87 unsigned brkincr = BRKINCR;
88 
89 unsigned char	*stakbot;
90 unsigned char	*staktop;
91 unsigned char	*brkend;
92 
93 /*
94  * Grow stak so "newtop" becomes part of the valid stak.
95  * Return new corrected address for "newtop".
96  */
97 unsigned char *
growstak(newtop)98 growstak(newtop)
99 	unsigned char	*newtop;
100 {
101 	UIntptr_t	incr;
102 	UIntptr_t	newoff = newtop - stakbot;
103 	UIntptr_t	curoff = staktop - stakbot;
104 	int		staklen;
105 	unsigned char	*new;
106 
107 	incr = (UIntptr_t)round(newtop - brkend + 1, BYTESPERWORD);
108 	if (brkincr > incr)
109 		incr = brkincr;		/* Grow at least by brkincr */
110 
111 	staklen = brkend - stakbot;
112 
113 	new = realloc(stakbot, staklen + incr);
114 	if (new) {
115 		staklen += incr;
116 		stakbot = new;
117 		staktop = stakbot + curoff;
118 		brkend = stakbot + staklen;
119 	} else {
120 		(void) fprintf(stderr, _("cannot allocate memory"));
121 		exit(1);
122 	}
123 
124 	return (stakbot + newoff);	/* New value for newtop */
125 }
126 
127 /*
128  * Append the string in "a" to the string pointed to by "b".
129  * "b" must be on the current local stack.
130  * Return the address of the nul character at the end of the new string.
131  *
132  * The stack is kept growable.
133  */
134 unsigned char *
movstrstak(a,b)135 movstrstak(a, b)
136 	unsigned char	*a;
137 	unsigned char	*b;
138 {
139 	do {
140 		if (b >= brkend)
141 			b = growstak(b);
142 	} while ((*b++ = *a++) != '\0');
143 	return (--b);
144 }
145 
146 /*
147  * This is the routine to enable POSIX untility syntax guidelines for builtins
148  * that do not implement options.
149  *
150  * Returns:
151  *		> 0	Arg index for next file type argument.
152  */
153 int
optskip(argc,argv,use)154 optskip(argc, argv, use)
155 	int	argc;
156 	unsigned char	**argv;
157 	const	 char	*use;
158 {
159 	int	opt_ind = 1;
160 
161 	if (argc > 1 &&
162 	    strcmp(C argv[1], "--") == 0) {	/* XCU4 "--" handling */
163 		opt_ind++;
164 		argv++;
165 	}
166 	return (opt_ind);
167 }
168