219{
221 int length;
223 int free_string_on_destroy;
224}
225
227
228
229
230
231
232
233
236{
239
242
246
248
251
254
255 return s;
256}
257
258
259static void
261{
263 return;
264
267
269}
270
271
272static void
274{
278}
279
280
283{
286
290
292}
293
294
295static int
297{
299
300 if ((pos < 0) || (pos >= s->
length))
301 return 0;
302
304 if ((
c ==
'A') || (
c ==
'E') || (
c ==
'I') || (
c ==
'O') ||
305 (
c ==
'U') || (
c ==
'Y'))
306 return 1;
307
308 return 0;
309}
310
311
312static int
314{
316 return 1;
318 return 1;
320 return 1;
322 return 1;
323 else
324 return 0;
325}
326
327
328static char
330{
331 if ((pos < 0) || (pos >= s->
length))
332 return '\0';
333
334 return *(s->
str + pos);
335}
336
337
338static void
340{
341 if ((pos < 0) || (pos >= s->
length))
342 return;
343
345}
346
347
348
349
350
351static int
353{
355 char *pos;
357
359 return 0;
360
363
364 do
365 {
368 {
370 return 1;
371 }
372 }
374
376
377 return 0;
378}
379
380
381static void
383{
385
387 return;
388
392
395}
396
397
398static void
400{
401 int length;
405 int current;
406 int last;
407
408 current = 0;
409
411 last = length - 1;
413
415
420
422
423
424 if (
StringAt(original, 0, 2,
"GN",
"KN",
"PN",
"WR",
"PS",
""))
425 current += 1;
426
427
428 if (
GetAt(original, 0) ==
'X')
429 {
432 current += 1;
433 }
434
435
437 {
438 if (current >= length)
439 break;
440
441 switch (
GetAt(original, current))
442 {
443 case 'A':
444 case 'E':
445 case 'I':
446 case 'O':
447 case 'U':
448 case 'Y':
449 if (current == 0)
450 {
451
454 }
455 current += 1;
456 break;
457
458 case 'B':
459
460
463
464 if (
GetAt(original, current + 1) ==
'B')
465 current += 2;
466 else
467 current += 1;
468 break;
469
470 case '\xc7':
473 current += 1;
474 break;
475
476 case 'C':
477
478 if ((current > 1)
479 && !
IsVowel(original, current - 2)
480 &&
StringAt(original, (current - 1), 3,
"ACH",
"")
481 && ((
GetAt(original, current + 2) !=
'I')
482 && ((
GetAt(original, current + 2) !=
'E')
483 ||
StringAt(original, (current - 2), 6,
"BACHER",
484 "MACHER", ""))))
485 {
488 current += 2;
489 break;
490 }
491
492
493 if ((current == 0)
494 &&
StringAt(original, current, 6,
"CAESAR",
""))
495 {
498 current += 2;
499 break;
500 }
501
502
503 if (
StringAt(original, current, 4,
"CHIA",
""))
504 {
507 current += 2;
508 break;
509 }
510
511 if (
StringAt(original, current, 2,
"CH",
""))
512 {
513
514 if ((current > 0)
515 &&
StringAt(original, current, 4,
"CHAE",
""))
516 {
519 current += 2;
520 break;
521 }
522
523
524 if ((current == 0)
525 && (
StringAt(original, (current + 1), 5,
526 "HARAC", "HARIS", "")
527 ||
StringAt(original, (current + 1), 3,
"HOR",
528 "HYM", "HIA", "HEM", ""))
529 && !
StringAt(original, 0, 5,
"CHORE",
""))
530 {
533 current += 2;
534 break;
535 }
536
537
538 if ((
StringAt(original, 0, 4,
"VAN ",
"VON ",
"")
539 ||
StringAt(original, 0, 3,
"SCH",
""))
540
541 ||
StringAt(original, (current - 2), 6,
"ORCHES",
542 "ARCHIT", "ORCHID", "")
543 ||
StringAt(original, (current + 2), 1,
"T",
"S",
544 "")
545 || ((
StringAt(original, (current - 1), 1,
546 "A", "O", "U", "E", "")
547 || (current == 0))
548
549
550
551
552 &&
StringAt(original, (current + 2), 1,
"L",
"R",
553 "N", "M", "B", "H", "F", "V", "W",
554 " ", "")))
555 {
558 }
559 else
560 {
561 if (current > 0)
562 {
563 if (
StringAt(original, 0, 2,
"MC",
""))
564 {
565
568 }
569 else
570 {
573 }
574 }
575 else
576 {
579 }
580 }
581 current += 2;
582 break;
583 }
584
585 if (
StringAt(original, current, 2,
"CZ",
"")
586 && !
StringAt(original, (current - 2), 4,
"WICZ",
""))
587 {
590 current += 2;
591 break;
592 }
593
594
595 if (
StringAt(original, (current + 1), 3,
"CIA",
""))
596 {
599 current += 3;
600 break;
601 }
602
603
604 if (
StringAt(original, current, 2,
"CC",
"")
605 && !((current == 1) && (
GetAt(original, 0) ==
'M')))
606 {
607
608 if (
StringAt(original, (current + 2), 1,
"I",
"E",
"H",
"")
609 && !
StringAt(original, (current + 2), 2,
"HU",
""))
610 {
611
612 if (((current == 1)
613 && (
GetAt(original, current - 1) ==
'A'))
614 ||
StringAt(original, (current - 1), 5,
"UCCEE",
615 "UCCES", ""))
616 {
619
620 }
621 else
622 {
625 }
626 current += 3;
627 break;
628 }
629 else
630 {
633 current += 2;
634 break;
635 }
636 }
637
638 if (
StringAt(original, current, 2,
"CK",
"CG",
"CQ",
""))
639 {
642 current += 2;
643 break;
644 }
645
646 if (
StringAt(original, current, 2,
"CI",
"CE",
"CY",
""))
647 {
648
650 (original, current, 3, "CIO", "CIE", "CIA", ""))
651 {
654 }
655 else
656 {
659 }
660 current += 2;
661 break;
662 }
663
664
667
668
669 if (
StringAt(original, (current + 1), 2,
" C",
" Q",
" G",
""))
670 current += 3;
671 else if (
StringAt(original, (current + 1), 1,
"C",
"K",
"Q",
"")
672 && !
StringAt(original, (current + 1), 2,
673 "CE", "CI", ""))
674 current += 2;
675 else
676 current += 1;
677 break;
678
679 case 'D':
680 if (
StringAt(original, current, 2,
"DG",
""))
681 {
682 if (
StringAt(original, (current + 2), 1,
683 "I", "E", "Y", ""))
684 {
685
688 current += 3;
689 break;
690 }
691 else
692 {
693
696 current += 2;
697 break;
698 }
699 }
700
701 if (
StringAt(original, current, 2,
"DT",
"DD",
""))
702 {
705 current += 2;
706 break;
707 }
708
709
712 current += 1;
713 break;
714
715 case 'F':
716 if (
GetAt(original, current + 1) ==
'F')
717 current += 2;
718 else
719 current += 1;
722 break;
723
724 case 'G':
725 if (
GetAt(original, current + 1) ==
'H')
726 {
727 if ((current > 0) && !
IsVowel(original, current - 1))
728 {
731 current += 2;
732 break;
733 }
734
735 if (current < 3)
736 {
737
738 if (current == 0)
739 {
740 if (
GetAt(original, current + 2) ==
'I')
741 {
744 }
745 else
746 {
749 }
750 current += 2;
751 break;
752 }
753 }
754
755
756
757
758
759 if (((current > 1)
760 &&
StringAt(original, (current - 2), 1,
761 "B", "H", "D", ""))
762
763 || ((current > 2)
764 &&
StringAt(original, (current - 3), 1,
765 "B", "H", "D", ""))
766
767 || ((current > 3)
768 &&
StringAt(original, (current - 4), 1,
769 "B", "H", "")))
770 {
771 current += 2;
772 break;
773 }
774 else
775 {
776
777
778
779
780 if ((current > 2)
781 && (
GetAt(original, current - 1) ==
'U')
782 &&
StringAt(original, (current - 3), 1,
"C",
783 "G", "L", "R", "T", ""))
784 {
787 }
788 else if ((current > 0)
789 &&
GetAt(original, current - 1) !=
'I')
790 {
791
792
795 }
796
797 current += 2;
798 break;
799 }
800 }
801
802 if (
GetAt(original, current + 1) ==
'N')
803 {
804 if ((current == 1) &&
IsVowel(original, 0)
806 {
809 }
810 else
811
812 if (!
StringAt(original, (current + 2), 2,
"EY",
"")
813 && (
GetAt(original, current + 1) !=
'Y')
815 {
818 }
819 else
820 {
823 }
824 current += 2;
825 break;
826 }
827
828
829 if (
StringAt(original, (current + 1), 2,
"LI",
"")
831 {
834 current += 2;
835 break;
836 }
837
838
839 if ((current == 0)
840 && ((
GetAt(original, current + 1) ==
'Y')
841 ||
StringAt(original, (current + 1), 2,
"ES",
"EP",
842 "EB", "EL", "EY", "IB", "IL", "IN", "IE",
843 "EI", "ER", "")))
844 {
847 current += 2;
848 break;
849 }
850
851
852 if ((
StringAt(original, (current + 1), 2,
"ER",
"")
853 || (
GetAt(original, current + 1) ==
'Y'))
855 "DANGER", "RANGER", "MANGER", "")
856 && !
StringAt(original, (current - 1), 1,
"E",
"I",
"")
857 && !
StringAt(original, (current - 1), 3,
"RGY",
"OGY",
""))
858 {
861 current += 2;
862 break;
863 }
864
865
866 if (
StringAt(original, (current + 1), 1,
"E",
"I",
"Y",
"")
867 ||
StringAt(original, (current - 1), 4,
868 "AGGI", "OGGI", ""))
869 {
870
871 if ((
StringAt(original, 0, 4,
"VAN ",
"VON ",
"")
872 ||
StringAt(original, 0, 3,
"SCH",
""))
873 ||
StringAt(original, (current + 1), 2,
"ET",
""))
874 {
877 }
878 else
879 {
880
882 (original, (current + 1), 4, "IER ", ""))
883 {
886 }
887 else
888 {
891 }
892 }
893 current += 2;
894 break;
895 }
896
897 if (
GetAt(original, current + 1) ==
'G')
898 current += 2;
899 else
900 current += 1;
903 break;
904
905 case 'H':
906
907 if (((current == 0) ||
IsVowel(original, current - 1))
908 &&
IsVowel(original, current + 1))
909 {
912 current += 2;
913 }
914 else
915
916 current += 1;
917 break;
918
919 case 'J':
920
921 if (
StringAt(original, current, 4,
"JOSE",
"")
922 ||
StringAt(original, 0, 4,
"SAN ",
""))
923 {
924 if (((current == 0)
925 && (
GetAt(original, current + 4) ==
' '))
926 ||
StringAt(original, 0, 4,
"SAN ",
""))
927 {
930 }
931 else
932 {
935 }
936 current += 1;
937 break;
938 }
939
940 if ((current == 0)
941 && !
StringAt(original, current, 4,
"JOSE",
""))
942 {
945 }
946 else
947 {
948
949 if (
IsVowel(original, current - 1)
951 && ((
GetAt(original, current + 1) ==
'A')
952 || (
GetAt(original, current + 1) ==
'O')))
953 {
956 }
957 else
958 {
959 if (current == last)
960 {
963 }
964 else
965 {
966 if (!
StringAt(original, (current + 1), 1,
"L",
"T",
967 "K", "S", "N", "M", "B", "Z", "")
968 && !
StringAt(original, (current - 1), 1,
969 "S", "K", "L", ""))
970 {
973 }
974 }
975 }
976 }
977
978 if (
GetAt(original, current + 1) ==
'J')
979 current += 2;
980 else
981 current += 1;
982 break;
983
984 case 'K':
985 if (
GetAt(original, current + 1) ==
'K')
986 current += 2;
987 else
988 current += 1;
991 break;
992
993 case 'L':
994 if (
GetAt(original, current + 1) ==
'L')
995 {
996
997 if (((current == (length - 3))
998 &&
StringAt(original, (current - 1), 4,
"ILLO",
999 "ILLA", "ALLE", ""))
1000 || ((
StringAt(original, (last - 1), 2,
"AS",
"OS",
"")
1001 ||
StringAt(original, last, 1,
"A",
"O",
""))
1002 &&
StringAt(original, (current - 1), 4,
1003 "ALLE", "")))
1004 {
1007 current += 2;
1008 break;
1009 }
1010 current += 2;
1011 }
1012 else
1013 current += 1;
1016 break;
1017
1018 case 'M':
1019 if ((
StringAt(original, (current - 1), 3,
"UMB",
"")
1020 && (((current + 1) == last)
1021 ||
StringAt(original, (current + 2), 2,
"ER",
"")))
1022
1023 || (
GetAt(original, current + 1) ==
'M'))
1024 current += 2;
1025 else
1026 current += 1;
1029 break;
1030
1031 case 'N':
1032 if (
GetAt(original, current + 1) ==
'N')
1033 current += 2;
1034 else
1035 current += 1;
1038 break;
1039
1040 case '\xd1':
1041 current += 1;
1044 break;
1045
1046 case 'P':
1047 if (
GetAt(original, current + 1) ==
'H')
1048 {
1051 current += 2;
1052 break;
1053 }
1054
1055
1056 if (
StringAt(original, (current + 1), 1,
"P",
"B",
""))
1057 current += 2;
1058 else
1059 current += 1;
1062 break;
1063
1064 case 'Q':
1065 if (
GetAt(original, current + 1) ==
'Q')
1066 current += 2;
1067 else
1068 current += 1;
1071 break;
1072
1073 case 'R':
1074
1075 if ((current == last)
1077 &&
StringAt(original, (current - 2), 2,
"IE",
"")
1078 && !
StringAt(original, (current - 4), 2,
"ME",
"MA",
""))
1079 {
1082 }
1083 else
1084 {
1087 }
1088
1089 if (
GetAt(original, current + 1) ==
'R')
1090 current += 2;
1091 else
1092 current += 1;
1093 break;
1094
1095 case 'S':
1096
1097 if (
StringAt(original, (current - 1), 3,
"ISL",
"YSL",
""))
1098 {
1099 current += 1;
1100 break;
1101 }
1102
1103
1104 if ((current == 0)
1105 &&
StringAt(original, current, 5,
"SUGAR",
""))
1106 {
1109 current += 1;
1110 break;
1111 }
1112
1113 if (
StringAt(original, current, 2,
"SH",
""))
1114 {
1115
1117 (original, (current + 1), 4, "HEIM", "HOEK", "HOLM",
1118 "HOLZ", ""))
1119 {
1122 }
1123 else
1124 {
1127 }
1128 current += 2;
1129 break;
1130 }
1131
1132
1133 if (
StringAt(original, current, 3,
"SIO",
"SIA",
"")
1134 ||
StringAt(original, current, 4,
"SIAN",
""))
1135 {
1137 {
1140 }
1141 else
1142 {
1145 }
1146 current += 3;
1147 break;
1148 }
1149
1150
1151
1152
1153
1154
1155 if (((current == 0)
1156 &&
StringAt(original, (current + 1), 1,
1157 "M", "N", "L", "W", ""))
1158 ||
StringAt(original, (current + 1), 1,
"Z",
""))
1159 {
1162 if (
StringAt(original, (current + 1), 1,
"Z",
""))
1163 current += 2;
1164 else
1165 current += 1;
1166 break;
1167 }
1168
1169 if (
StringAt(original, current, 2,
"SC",
""))
1170 {
1171
1172 if (
GetAt(original, current + 2) ==
'H')
1173 {
1174
1175 if (
StringAt(original, (current + 3), 2,
1176 "OO", "ER", "EN",
1177 "UY", "ED", "EM", ""))
1178 {
1179
1180 if (
StringAt(original, (current + 3), 2,
1181 "ER", "EN", ""))
1182 {
1185 }
1186 else
1187 {
1190 }
1191 current += 3;
1192 break;
1193 }
1194 else
1195 {
1196 if ((current == 0) && !
IsVowel(original, 3)
1197 && (
GetAt(original, 3) !=
'W'))
1198 {
1201 }
1202 else
1203 {
1206 }
1207 current += 3;
1208 break;
1209 }
1210 }
1211
1212 if (
StringAt(original, (current + 2), 1,
1213 "I", "E", "Y", ""))
1214 {
1217 current += 3;
1218 break;
1219 }
1220
1223 current += 3;
1224 break;
1225 }
1226
1227
1228 if ((current == last)
1229 &&
StringAt(original, (current - 2), 2,
"AI",
"OI",
""))
1230 {
1233 }
1234 else
1235 {
1238 }
1239
1240 if (
StringAt(original, (current + 1), 1,
"S",
"Z",
""))
1241 current += 2;
1242 else
1243 current += 1;
1244 break;
1245
1246 case 'T':
1247 if (
StringAt(original, current, 4,
"TION",
""))
1248 {
1251 current += 3;
1252 break;
1253 }
1254
1255 if (
StringAt(original, current, 3,
"TIA",
"TCH",
""))
1256 {
1259 current += 3;
1260 break;
1261 }
1262
1263 if (
StringAt(original, current, 2,
"TH",
"")
1264 ||
StringAt(original, current, 3,
"TTH",
""))
1265 {
1266
1267 if (
StringAt(original, (current + 2), 2,
"OM",
"AM",
"")
1268 ||
StringAt(original, 0, 4,
"VAN ",
"VON ",
"")
1269 ||
StringAt(original, 0, 3,
"SCH",
""))
1270 {
1273 }
1274 else
1275 {
1278 }
1279 current += 2;
1280 break;
1281 }
1282
1283 if (
StringAt(original, (current + 1), 1,
"T",
"D",
""))
1284 current += 2;
1285 else
1286 current += 1;
1289 break;
1290
1291 case 'V':
1292 if (
GetAt(original, current + 1) ==
'V')
1293 current += 2;
1294 else
1295 current += 1;
1298 break;
1299
1300 case 'W':
1301
1302 if (
StringAt(original, current, 2,
"WR",
""))
1303 {
1306 current += 2;
1307 break;
1308 }
1309
1310 if ((current == 0)
1311 && (
IsVowel(original, current + 1)
1312 ||
StringAt(original, current, 2,
"WH",
"")))
1313 {
1314
1315 if (
IsVowel(original, current + 1))
1316 {
1319 }
1320 else
1321 {
1322
1325 }
1326 }
1327
1328
1329 if (((current == last) &&
IsVowel(original, current - 1))
1330 ||
StringAt(original, (current - 1), 5,
"EWSKI",
"EWSKY",
1331 "OWSKI", "OWSKY", "")
1332 ||
StringAt(original, 0, 3,
"SCH",
""))
1333 {
1336 current += 1;
1337 break;
1338 }
1339
1340
1341 if (
StringAt(original, current, 4,
"WICZ",
"WITZ",
""))
1342 {
1345 current += 4;
1346 break;
1347 }
1348
1349
1350 current += 1;
1351 break;
1352
1353 case 'X':
1354
1355 if (!((current == last)
1356 && (
StringAt(original, (current - 3), 3,
1357 "IAU", "EAU", "")
1358 ||
StringAt(original, (current - 2), 2,
1359 "AU", "OU", ""))))
1360 {
1363 }
1364
1365
1366 if (
StringAt(original, (current + 1), 1,
"C",
"X",
""))
1367 current += 2;
1368 else
1369 current += 1;
1370 break;
1371
1372 case 'Z':
1373
1374 if (
GetAt(original, current + 1) ==
'H')
1375 {
1378 current += 2;
1379 break;
1380 }
1381 else if (
StringAt(original, (current + 1), 2,
1382 "ZO", "ZI", "ZA", "")
1384 && ((current > 0)
1385 &&
GetAt(original, current - 1) !=
'T')))
1386 {
1389 }
1390 else
1391 {
1394 }
1395
1396 if (
GetAt(original, current + 1) ==
'Z')
1397 current += 2;
1398 else
1399 current += 1;
1400 break;
1401
1402 default:
1403 current += 1;
1404 }
1405
1406
1407
1408
1409
1410 }
1411
1412
1414 SetAt(primary, 4,
'\0');
1415
1418
1421
1425}
1426
1427#ifdef DMETAPHONE_MAIN
1428
1429
1430
1431main(
int argc,
char **argv)
1432{
1434
1435 if (argc > 1)
1436 {
1439 }
1440}
1441
1442#endif