00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "mit-copyright.h"
00010
00011 #include "char_stack.h"
00012 #include "string_dictionary.h"
00013 #include "formatter.h"
00014 #include "text_operations.h"
00015
00016 #if !defined(__STDC__) && !defined(const)
00017 #define const
00018 #endif
00019
00020 static int pure_text_length(), env_length();
00021
00022 static const character_class paren_set = {
00023 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00024 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00025 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
00026 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00027 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00028 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00029 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00030 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00031 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00032 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00033 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00034 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00035 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00036 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00037 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00038 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00039 };
00040
00041 static const character_class sbracket_set = {
00042 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00043 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00044 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00045 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00046 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00047 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
00048 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00049 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00050 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00051 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00052 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00053 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00054 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00055 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00056 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00057 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00058 };
00059
00060 static const character_class abracket_set = {
00061 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00062 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00063 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00064 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
00065 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00066 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00067 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00068 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00069 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00070 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00071 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00072 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00073 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00074 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00075 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00076 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00077 };
00078
00079 static const character_class cbracket_set = {
00080 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00081 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00082 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00083 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00084 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00085 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00086 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00087 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
00088 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00089 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00090 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00091 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00092 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00093 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00094 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00095 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00096 };
00097
00098 static const character_class allbracket_set = {
00099 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00100 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00101 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
00102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
00103 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00104 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
00105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00106 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
00107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00114 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00115 };
00116
00117 static const character_class allmaskable_set = {
00118 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00120 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
00121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
00122 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
00124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00125 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
00126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00128 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00134 };
00135
00136 static char brackets[] = "()<>[]{}@";
00137 static char *openbracket[] = {"@<", "@<", "@[", "@[", "@{", "@{", "@(", "@(", "@("};
00138 static char *closebracket[] = {">", ">", "]", "]", "}", "}", ")", ")", ")"};
00139
00140 static int
00141 not_contains(str, set)
00142 string str;
00143 const character_class set;
00144 {
00145 while (*str && !set[(int) *str])
00146 str++;
00147 return (!*str);
00148 }
00149
00150 static int
00151 pure_text_length(text, terminator)
00152 char *text;
00153 char terminator;
00154 {
00155 int len = 0;
00156
00157 while (1) {
00158 while (*text != '@' && *text != terminator && *text) {
00159 text++;
00160 len++;
00161 }
00162
00163 if (*text != '@')
00164 return (len);
00165
00166 if (*(text + 1) == '@') {
00167 text++;
00168 len++;
00169 }
00170 else if (env_length(text + 1) != -1)
00171 return (len);
00172
00173 text++;
00174 len++;
00175 }
00176 }
00177
00178 static char
00179 otherside(opener)
00180 char opener;
00181 {
00182 switch (opener) {
00183 case '(':
00184 return (')');
00185 case '{':
00186 return ('}');
00187 case '[':
00188 return (']');
00189 case '<':
00190 return ('>');
00191 }
00192
00193 return (0);
00194 }
00195
00196
00197
00198
00199
00200 string
00201 verbatim(str, bracketsonly)
00202 string str;
00203 int bracketsonly;
00204 {
00205 char *temp, *temp2;
00206 int bracketnum, len;
00207
00208 if (strlen(str) == pure_text_length(str, 0)) {
00209
00210
00211 if (not_contains(str, allbracket_set)) {
00212 temp = string_Copy(str);
00213 free(str);
00214 return (temp);
00215 }
00216
00217 if (not_contains(str, abracket_set)) {
00218 temp = (char *) malloc((len = strlen(str)) + 4);
00219 temp[0] = '@';
00220 temp[1] = '<';
00221 (void) memcpy(temp + 2, str, len);
00222 temp[len + 2] = '>';
00223 temp[len + 3] = '\0';
00224 free(str);
00225 return (temp);
00226 }
00227 if (not_contains(str, sbracket_set)) {
00228 temp = (char *) malloc((len = strlen(str)) + 4);
00229 temp[0] = '@';
00230 temp[1] = '[';
00231 (void) memcpy(temp + 2, str, len);
00232 temp[len + 2] = ']';
00233 temp[len + 3] = '\0';
00234 free(str);
00235 return (temp);
00236 }
00237 if (not_contains(str, cbracket_set)) {
00238 temp = (char *) malloc((len = strlen(str)) + 4);
00239 temp[0] = '@';
00240 temp[1] = '{';
00241 (void) memcpy(temp + 2, str, len);
00242 temp[len + 2] = '}';
00243 temp[len + 3] = '\0';
00244 free(str);
00245 return (temp);
00246 }
00247 if (not_contains(str, paren_set)) {
00248 temp = (char *) malloc((len = strlen(str)) + 4);
00249 temp[0] = '@';
00250 temp[1] = '(';
00251 (void) memcpy(temp + 2, str, len);
00252 temp[len + 2] = ')';
00253 temp[len + 3] = '\0';
00254 free(str);
00255 return (temp);
00256 }
00257 }
00258
00259 temp = lbreak(&str, bracketsonly ? allbracket_set : allmaskable_set);
00260 while (*str) {
00261 bracketnum = (int) (strchr(brackets, str[0]) - brackets);
00262 temp = string_Concat2(temp, openbracket[bracketnum]);
00263 temp = string_Concat2(temp, temp2 = lany(&str, " "));
00264 free(temp2);
00265 temp = string_Concat2(temp, closebracket[bracketnum]);
00266 temp = string_Concat2(temp, temp2 = lbreak(&str, bracketsonly ?
00267 allbracket_set : allmaskable_set));
00268 free(temp2);
00269 }
00270 free(str);
00271
00272 return (temp);
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282 string
00283 protect(str)
00284 string str;
00285 {
00286 string temp, temp2, temp3;
00287 int len, templen;
00288 char_stack chs;
00289 char tos;
00290
00291 temp = string_Copy("");
00292 templen = 1;
00293 chs = char_stack_create();
00294
00295 while (*str) {
00296 tos = (char_stack_empty(chs) ? 0 : char_stack_top(chs));
00297
00298 if (*str == tos) {
00299
00300
00301 temp = (char *) realloc(temp, ++templen);
00302 temp[templen - 2] = *str++;
00303 char_stack_pop(chs);
00304 temp[templen - 1] = '\0';
00305 }
00306 else if ((len = pure_text_length(str, tos))) {
00307 if (tos) {
00308
00309
00310
00311
00312
00313 temp2 = string_CreateFromData(str, len);
00314 str += len;
00315 temp = string_Concat2(temp, temp2);
00316 templen += len;
00317 free(temp2);
00318 }
00319 else {
00320
00321
00322
00323
00324
00325
00326 temp2 = string_CreateFromData(str, len);
00327 str += len;
00328 temp3 = verbatim(temp2, 1);
00329 temp = string_Concat2(temp, temp3);
00330 templen += strlen(temp3);
00331 free(temp3);
00332 }
00333 }
00334 else {
00335
00336
00337
00338
00339
00340 len = env_length(str + 1);
00341 char_stack_push(chs, otherside(str[len + 1]));
00342 len += 2;
00343 temp2 = string_CreateFromData(str, len);
00344 str += len;
00345 temp = string_Concat2(temp, temp2);
00346 templen += len;
00347 free(temp2);
00348 }
00349 }
00350
00351
00352 while (!char_stack_empty(chs)) {
00353 temp = (char *) realloc(temp, ++templen);
00354 temp[templen - 2] = char_stack_top(chs);
00355 char_stack_pop(chs);
00356 }
00357 temp[templen - 1] = '\0';
00358
00359 return (temp);
00360 }
00361
00362 void
00363 free_desc(desc)
00364 desctype *desc;
00365 {
00366 desctype *next_desc;
00367
00368 while (desc->code != DT_EOF) {
00369 next_desc = desc->next;
00370 free(desc);
00371 desc = next_desc;
00372 }
00373 free(desc);
00374 }
00375
00376
00377
00378
00379
00380 static int
00381 env_length(text)
00382 char *text;
00383 {
00384 int len = 0;
00385
00386 while (*text && (isalnum(*text) || *text == '_')) {
00387 text++;
00388 len++;
00389 }
00390
00391 if ((*text == '(') || (*text == '{') || (*text == '[') || (*text == '<'))
00392 return (len);
00393 else
00394 return (-1);
00395 }
00396
00397
00398
00399
00400
00401
00402 static int
00403 text_length(text, terminator)
00404 char *text;
00405 char terminator;
00406 {
00407 int len = 0;
00408
00409 while (1) {
00410 while (*text != '@' && *text != '\n' && *text != terminator && *text) {
00411 text++;
00412 len++;
00413 }
00414
00415 if (*text != '@')
00416 return (len);
00417
00418 if (*(text + 1) == '@')
00419 (void) memmove(text + 1, text + 2, strlen(text + 1));
00420 else if (env_length(text + 1) != -1)
00421 return (len);
00422
00423 text++;
00424 len++;
00425 }
00426 }
00427
00428
00429
00430
00431
00432
00433 desctype *
00434 disp_get_cmds(str, pstr, pnl)
00435 char *str;
00436 int *pstr, *pnl;
00437 {
00438 desctype *desc, *here;
00439 int len;
00440 char_stack terminators = char_stack_create();
00441 char terminator;
00442 int nstr = 0, nnl = 0;
00443 char *curstr;
00444
00445 desc = (desctype *) malloc(sizeof(desctype));
00446 here = desc;
00447 curstr = str;
00448 terminator = '\0';
00449
00450 while (*curstr) {
00451 if (*curstr == '\n') {
00452 here->code = DT_NL;
00453 curstr++;
00454 nnl++;
00455 }
00456 else if (*curstr == terminator) {
00457
00458 here->code = DT_END;
00459 terminator = char_stack_top(terminators);
00460 char_stack_pop(terminators);
00461 curstr++;
00462 }
00463 else if ((len = text_length(curstr, terminator))) {
00464
00465 here->code = DT_STR;
00466 here->str = curstr;
00467 here->len = len;
00468 curstr += len;
00469 nstr++;
00470 }
00471 else if (*curstr == '@') {
00472
00473 len = env_length(curstr + 1);
00474 here->code = DT_ENV;
00475 here->str = curstr + 1;
00476 here->len = len;
00477 char_stack_push(terminators, terminator);
00478 terminator = otherside(*(curstr + 1 + len));
00479 curstr += (len + 2);
00480
00481 }
00482
00483 here->next = (desctype *) malloc(sizeof(desctype));
00484 here = here->next;
00485 }
00486
00487 while (!char_stack_empty(terminators)) {
00488 here->code = DT_END;
00489 terminator = char_stack_top(terminators);
00490 char_stack_pop(terminators);
00491 here->next = (desctype *) malloc(sizeof(desctype));
00492 here = here->next;
00493 }
00494 here->code = DT_EOF;
00495 *pstr = nstr;
00496 *pnl = nnl;
00497
00498 return (desc);
00499 }