1 /* 2 * string.c - string support functions for cawf(1) 3 */ 4 5 /* 6 * Copyright (c) 1991 Purdue University Research Foundation, 7 * West Lafayette, Indiana 47907. All rights reserved. 8 * 9 * Written by Victor A. Abell <abe@mace.cc.purdue.edu>, Purdue 10 * University Computing Center. Not derived from licensed software; 11 * derived from awf(1) by Henry Spencer of the University of Toronto. 12 * 13 * Permission is granted to anyone to use this software for any 14 * purpose on any computer system, and to alter it and redistribute 15 * it freely, subject to the following restrictions: 16 * 17 * 1. The author is not responsible for any consequences of use of 18 * this software, even if they arise from flaws in it. 19 * 20 * 2. The origin of this software must not be misrepresented, either 21 * by explicit claim or by omission. Credits must appear in the 22 * documentation. 23 * 24 * 3. Altered versions must be plainly marked as such, and must not 25 * be misrepresented as being the original software. Credits must 26 * appear in the documentation. 27 * 28 * 4. This notice may not be removed or altered. 29 */ 30 31 #include "cawf.h" 32 #include <ctype.h> 33 34 static void Setroman(void); 35 36 37 /* 38 * Asmname(s, c) - assemble name 39 */ 40 41 int Asmname(unsigned char *s, unsigned char *c) { 42 /* pointer to name s 43 * code destination (c[3]) 44 */ 45 c[1] = c[2] = '\0'; 46 while (*s && *s == ' ') 47 s++; 48 if ((c[0] = *s) == '\0') 49 return(0); 50 return(((c[1] = s[1]) == '\0') ? 1 : 2); 51 } 52 53 54 /* 55 * Delstr(sx) - delete string 56 */ 57 58 void Delstr(int sx) { 59 /* string index sx */ 60 char buf[MAXLINE]; /* message buffer */ 61 62 if (sx >= Nstr) { 63 (void) sprintf(buf, " bad Delstr(%d) index", sx); 64 Error(FATAL, LINE, buf, NULL); 65 } 66 Free(&Str[sx].str); 67 while (sx < (Nstr - 1)) { 68 Str[sx] = Str[sx + 1]; 69 sx++; 70 } 71 Nstr--; 72 } 73 74 75 /* 76 * Endword() - end a word 77 */ 78 79 void Endword(void) { 80 if (Fontstat != 'R') 81 Setroman(); 82 Word[Wordx] = '\0'; 83 } 84 85 86 /* 87 * Findchar(nm, l, s, e) - find special character definition and 88 * optionally enter it 89 */ 90 91 int Findchar(unsigned char *nm, int l, unsigned char *s, int e) { 92 /* character name nm 93 * effective length l 94 * value string s 95 * e = 0 = find, don't enter 96 * e = 1 = don't find, enter 97 */ 98 int cmp, hi, low, mid; 99 unsigned char c[3]; 100 101 c[0] = nm[0]; 102 c[1] = (nm[1] == ' ' || nm[1] == '\t') ? '\0' : nm[1]; 103 c[2] = '\0'; 104 low = mid = 0; 105 hi = Nsch - 1; 106 while (low <= hi) { 107 mid = (low + hi) / 2; 108 if ((cmp = strncmp((char *)c, (char *)Schar[mid].nm, 2)) < 0) 109 hi = mid - 1; 110 else if (cmp > 0) 111 low = mid + 1; 112 else { 113 if ( ! e) 114 return(mid); 115 Free(&Schar[mid].str); 116 goto new_char; 117 } 118 } 119 if ( ! e) 120 return(-1); 121 if (Nsch >= MAXSCH) 122 Error(FATAL, LINE, " at character table limit", NULL); 123 if (Nsch) { 124 if (cmp > 0) 125 mid++; 126 for (hi = Nsch - 1; hi >= mid; hi--) 127 Schar[hi+1] = Schar[hi]; 128 } 129 Nsch++; 130 Schar[mid].nm[0] = c[0]; 131 Schar[mid].nm[1] = c[1]; 132 133 new_char: 134 135 Schar[mid].str = Newstr(s); 136 Schar[mid].len = l; 137 return(mid); 138 } 139 140 141 /* 142 * Findhy(s, l, e) - find and optionally enter hyphen 143 */ 144 145 int Findhy(unsigned char *s, int l, int e) { 146 /* value string s 147 * equivalent length l 148 * e = 0 = find, don't enter 149 * e = 1 = enter, don't find 150 */ 151 int i; 152 153 for (i = 0; i < Nhy; i++) { 154 if (Font[0] == Hychar[i].font) 155 break; 156 } 157 if (i >= Nhy) { 158 if ( ! e) 159 return(-1); 160 if (Nhy >= MAXHYCH) 161 Error(FATAL, LINE, " at hyphen limit for font ", 162 (char *)Font); 163 Hychar[i].font = Font[0]; 164 Nhy++; 165 } else { 166 if ( ! e) 167 return(i); 168 Error(WARN, LINE, " duplicate hyphen for font ", (char *)Font); 169 Free(&Hychar[i].str); 170 } 171 Hychar[i].str = Newstr(s); 172 Hychar[i].len = l; 173 return(i); 174 } 175 176 177 /* 178 * Findstr(nm, s, e) - find and optionally enter string in Str[] 179 */ 180 181 unsigned char *Findstr(unsigned char *nm, unsigned char *s, int e) { 182 /* 2 character string name nm 183 * string value s 184 * e = 0 = find, don't enter 185 * e = 1 = enter, don't find 186 */ 187 unsigned char c[3]; /* character buffer */ 188 int cmp, hi, low, mid; /* binary search controls */ 189 int i; /* temporary indexes */ 190 unsigned char *s1, *s2; /* temporary string pointers */ 191 192 c[0] = nm[0]; 193 c[1] = (nm[1] == ' ' || nm[1] == '\t') ? '\0' : nm[1]; 194 c[2] = '\0'; 195 low = mid = 0; 196 hi = Nstr - 1; 197 Sx = -1; 198 while (low <= hi) { 199 mid = (low + hi) / 2; 200 if ((cmp = strncmp((char *)c, (char *)Str[mid].nm, 2)) < 0) 201 hi = mid - 1; 202 else if (cmp > 0) 203 low = mid + 1; 204 else { 205 Sx = mid; 206 if ( ! e) 207 return(Str[mid].str); 208 Free(&Str[mid].str); 209 goto new_string; 210 } 211 } 212 if ( ! e) 213 return((unsigned char *)""); 214 if (Nstr >= MAXSTR) 215 Error(FATAL, LINE, " out of space for string ", (char *)c); 216 if (Nstr) { 217 if (cmp > 0) 218 mid++; 219 for (hi = Nstr - 1; hi >= mid; hi--) 220 Str[hi+1] = Str[hi]; 221 } 222 Nstr++; 223 Sx = mid; 224 Str[mid].nm[0] = c[0]; 225 Str[mid].nm[1] = c[1]; 226 227 new_string: 228 229 if (s == NULL) 230 return (Str[mid].str = Newstr((unsigned char *)"")); 231 i = (*s == '"') ? 1 : 0; 232 s1 = Str[mid].str = Newstr(s + i); 233 if (i) { 234 s2 = s1 + strlen((char *)s1); 235 if (s2 > s1 && *(s2-1) == '"') 236 *(s2-1) = '\0'; 237 } 238 return(s1); 239 } 240 241 242 /* 243 * Setroman() - set Roman font 244 */ 245 246 static void Setroman(void) { 247 int i; 248 249 if ((Wordx + Fstr.rl) >= MAXLINE) 250 Error(WARN, LINE, " word too long", NULL); 251 else { 252 if (Fstr.r) { 253 for (i = 0; i < Fstr.rl; i++) { 254 Word[Wordx++] = Fstr.r[i]; 255 } 256 } 257 Fontstat = 'R'; 258 } 259 } 260 261 262 /* 263 * Str2word(s, len) - copy len characters from string to Word[] 264 */ 265 266 int Str2word(unsigned char *s, int len) { 267 int i; 268 269 for (; len > 0; len--, s++) { 270 switch (Font[0]) { 271 case 'B': 272 case 'C': 273 if (Fontctl == 0) { 274 if ((Wordx + 5) >= MAXLINE) { 275 word_too_long: 276 Error(WARN, LINE, " word too long", 277 NULL); 278 return(1); 279 } 280 Word[Wordx++] = Trtbl[(int)*s]; 281 Word[Wordx++] = '\b'; 282 Word[Wordx++] = Trtbl[(int)*s]; 283 Word[Wordx++] = '\b'; 284 Word[Wordx++] = Trtbl[(int)*s]; 285 break; 286 } 287 if (Fontstat != Font[0]) { 288 if (Fontstat != 'R') 289 Setroman(); 290 if ((Wordx + Fstr.bl) >= MAXLINE) 291 goto word_too_long; 292 if (Fstr.b) { 293 for (i = 0; i < Fstr.bl; i++) { 294 Word[Wordx++] = Fstr.b[i]; 295 } 296 } 297 Fontstat = Font[0]; 298 } 299 if ((Wordx + 1) >= MAXLINE) 300 goto word_too_long; 301 Word[Wordx++] = Trtbl[(int)*s]; 302 break; 303 case 'I': 304 if (isalnum(*s)) { 305 if (Fontctl == 0) { 306 if ((Wordx + 3) >= MAXLINE) 307 goto word_too_long; 308 Word[Wordx++] = '_'; 309 Word[Wordx++] = '\b'; 310 Word[Wordx++] = Trtbl[(int)*s]; 311 break; 312 } 313 if (Fontstat != 'I') { 314 if (Fontstat != 'R') 315 Setroman(); 316 if ((Wordx + Fstr.itl) >= MAXLINE) 317 goto word_too_long; 318 if (Fstr.it) { 319 for (i = 0; i < Fstr.itl; i++) { 320 Word[Wordx++] = Fstr.it[i]; 321 } 322 } 323 Fontstat = 'I'; 324 } 325 if ((Wordx + 1) >= MAXLINE) 326 goto word_too_long; 327 Word[Wordx++] = Trtbl[(int)*s]; 328 break; 329 } 330 /* else fall through */ 331 default: 332 if (Fontstat != 'R') 333 Setroman(); 334 if ((Wordx + 1) >= MAXLINE) 335 goto word_too_long; 336 Word[Wordx++] = Trtbl[(int)*s]; 337 } 338 } 339 return(0); 340 } 341