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