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(); 35 36 37 /* 38 * Asmname(s, c) - assemble name 39 */ 40 41 Asmname(s, c) 42 unsigned char *s; /* pointer to name */ 43 unsigned char *c; /* code destination (c[3]) */ 44 { 45 46 c[1] = c[2] = '\0'; 47 while (*s && *s == ' ') 48 s++; 49 if ((c[0] = *s) == '\0') 50 return(0); 51 return(((c[1] = s[1]) == '\0') ? 1 : 2); 52 } 53 54 55 /* 56 * Delstr(sx) - delete string 57 */ 58 59 void 60 Delstr(sx) 61 int sx; /* string index */ 62 { 63 char buf[MAXLINE]; /* message buffer */ 64 65 if (sx >= Nstr) { 66 (void) sprintf(buf, " bad Delstr(%d) index", sx); 67 Error(FATAL, LINE, buf, NULL); 68 } 69 Free(&Str[sx].str); 70 while (sx < (Nstr - 1)) { 71 Str[sx] = Str[sx + 1]; 72 sx++; 73 } 74 Nstr--; 75 } 76 77 78 /* 79 * Endword() - end a word 80 */ 81 82 void 83 Endword() 84 { 85 if (Fontstat != 'R') 86 Setroman(); 87 Word[Wordx] = '\0'; 88 } 89 90 91 /* 92 * Findchar(nm, l, s, e) - find special character definition and 93 * optionally enter it 94 */ 95 96 Findchar(nm, l, s, e) 97 unsigned char *nm; /* character name */ 98 int l; /* effective length */ 99 unsigned char *s; /* value string */ 100 int e; /* 0 = find, don't enter 101 * 1 = don't find, enter */ 102 { 103 int cmp, hi, low, mid; 104 unsigned char c[3]; 105 106 c[0] = nm[0]; 107 c[1] = (nm[1] == ' ' || nm[1] == '\t') ? '\0' : nm[1]; 108 c[2] = '\0'; 109 low = mid = 0; 110 hi = Nsch - 1; 111 while (low <= hi) { 112 mid = (low + hi) / 2; 113 if ((cmp = strncmp((char *)c, (char *)Schar[mid].nm, 2)) < 0) 114 hi = mid - 1; 115 else if (cmp > 0) 116 low = mid + 1; 117 else { 118 if ( ! e) 119 return(mid); 120 Free(&Schar[mid].str); 121 goto new_char; 122 } 123 } 124 if ( ! e) 125 return(-1); 126 if (Nsch >= MAXSCH) 127 Error(FATAL, LINE, " at character table limit", NULL); 128 if (Nsch) { 129 if (cmp > 0) 130 mid++; 131 for (hi = Nsch - 1; hi >= mid; hi--) 132 Schar[hi+1] = Schar[hi]; 133 } 134 Nsch++; 135 Schar[mid].nm[0] = c[0]; 136 Schar[mid].nm[1] = c[1]; 137 138 new_char: 139 140 Schar[mid].str = Newstr(s); 141 Schar[mid].len = l; 142 return(mid); 143 } 144 145 146 /* 147 * Findhy(s, l, e) - find and optionally enter hyphen 148 */ 149 150 Findhy(s, l, e) 151 unsigned char *s; /* value string */ 152 int l; /* equivalent length */ 153 int e; /* 0 = find, don't enter 154 * 1 = enter, don't find */ 155 { 156 int i; 157 158 for (i = 0; i < Nhy; i++) { 159 if (Font[0] == Hychar[i].font) 160 break; 161 } 162 if (i >= Nhy) { 163 if ( ! e) 164 return(-1); 165 if (Nhy >= MAXHYCH) 166 Error(FATAL, LINE, " at hyphen limit for font ", 167 (char *)Font); 168 Hychar[i].font = Font[0]; 169 Nhy++; 170 } else { 171 if ( ! e) 172 return(i); 173 Error(WARN, LINE, " duplicate hyphen for font ", (char *)Font); 174 Free(&Hychar[i].str); 175 } 176 Hychar[i].str = Newstr(s); 177 Hychar[i].len = l; 178 return(i); 179 } 180 181 182 /* 183 * Findstr(nm, s, e) - find and optionally enter string in Str[] 184 */ 185 186 unsigned char * 187 Findstr(nm, s, e) 188 unsigned char *nm; /* 2 character string name */ 189 unsigned char *s; /* string value */ 190 int e; /* 0 = find, don't enter 191 * 1 = enter, don't find */ 192 { 193 unsigned char c[3]; /* character buffer */ 194 int cmp, hi, low, mid; /* binary search controls */ 195 int i; /* temporary indexes */ 196 unsigned char *s1, *s2; /* temporary string pointers */ 197 198 c[0] = nm[0]; 199 c[1] = (nm[1] == ' ' || nm[1] == '\t') ? '\0' : nm[1]; 200 c[2] = '\0'; 201 low = mid = 0; 202 hi = Nstr - 1; 203 Sx = -1; 204 while (low <= hi) { 205 mid = (low + hi) / 2; 206 if ((cmp = strncmp((char *)c, (char *)Str[mid].nm, 2)) < 0) 207 hi = mid - 1; 208 else if (cmp > 0) 209 low = mid + 1; 210 else { 211 Sx = mid; 212 if ( ! e) 213 return(Str[mid].str); 214 Free(&Str[mid].str); 215 goto new_string; 216 } 217 } 218 if ( ! e) 219 return((unsigned char *)""); 220 if (Nstr >= MAXSTR) 221 Error(FATAL, LINE, " out of space for string ", (char *)c); 222 if (Nstr) { 223 if (cmp > 0) 224 mid++; 225 for (hi = Nstr - 1; hi >= mid; hi--) 226 Str[hi+1] = Str[hi]; 227 } 228 Nstr++; 229 Sx = mid; 230 Str[mid].nm[0] = c[0]; 231 Str[mid].nm[1] = c[1]; 232 233 new_string: 234 235 if (s == NULL) 236 return (Str[mid].str = Newstr((unsigned char *)"")); 237 i = (*s == '"') ? 1 : 0; 238 s1 = Str[mid].str = Newstr(s + i); 239 if (i) { 240 s2 = s1 + strlen((char *)s1); 241 if (s2 > s1 && *(s2-1) == '"') 242 *(s2-1) = '\0'; 243 } 244 return(s1); 245 } 246 247 248 /* 249 * Setroman() - set Roman font 250 */ 251 252 static void 253 Setroman() 254 { 255 int i; 256 257 if ((Wordx + Fstr.rl) >= MAXLINE) 258 Error(WARN, LINE, " word too long", NULL); 259 else { 260 if (Fstr.r) { 261 for (i = 0; i < Fstr.rl; i++) { 262 Word[Wordx++] = Fstr.r[i]; 263 } 264 } 265 Fontstat = 'R'; 266 } 267 } 268 269 270 /* 271 * Str2word(s, len) - copy len characters from string to Word[] 272 */ 273 274 Str2word(s, len) 275 unsigned char *s; 276 int len; 277 { 278 int i; 279 280 for (; len > 0; len--, s++) { 281 switch (Font[0]) { 282 case 'B': 283 case 'C': 284 if (Fontctl == 0) { 285 if ((Wordx + 5) >= MAXLINE) { 286 word_too_long: 287 Error(WARN, LINE, " word too long", 288 NULL); 289 return(1); 290 } 291 Word[Wordx++] = Trtbl[(int)*s]; 292 Word[Wordx++] = '\b'; 293 Word[Wordx++] = Trtbl[(int)*s]; 294 Word[Wordx++] = '\b'; 295 Word[Wordx++] = Trtbl[(int)*s]; 296 break; 297 } 298 if (Fontstat != Font[0]) { 299 if (Fontstat != 'R') 300 Setroman(); 301 if ((Wordx + Fstr.bl) >= MAXLINE) 302 goto word_too_long; 303 if (Fstr.b) { 304 for (i = 0; i < Fstr.bl; i++) { 305 Word[Wordx++] = Fstr.b[i]; 306 } 307 } 308 Fontstat = Font[0]; 309 } 310 if ((Wordx + 1) >= MAXLINE) 311 goto word_too_long; 312 Word[Wordx++] = Trtbl[(int)*s]; 313 break; 314 case 'I': 315 if (isalnum(*s)) { 316 if (Fontctl == 0) { 317 if ((Wordx + 3) >= MAXLINE) 318 goto word_too_long; 319 Word[Wordx++] = '_'; 320 Word[Wordx++] = '\b'; 321 Word[Wordx++] = Trtbl[(int)*s]; 322 break; 323 } 324 if (Fontstat != 'I') { 325 if (Fontstat != 'R') 326 Setroman(); 327 if ((Wordx + Fstr.itl) >= MAXLINE) 328 goto word_too_long; 329 if (Fstr.it) { 330 for (i = 0; i < Fstr.itl; i++) { 331 Word[Wordx++] = Fstr.it[i]; 332 } 333 } 334 Fontstat = 'I'; 335 } 336 if ((Wordx + 1) >= MAXLINE) 337 goto word_too_long; 338 Word[Wordx++] = Trtbl[(int)*s]; 339 break; 340 } 341 /* else fall through */ 342 default: 343 if (Fontstat != 'R') 344 Setroman(); 345 if ((Wordx + 1) >= MAXLINE) 346 goto word_too_long; 347 Word[Wordx++] = Trtbl[(int)*s]; 348 } 349 } 350 return(0); 351 } 352