Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX(a, b) (a > b) ? a : b
#define MIN(a, b) (a < b) ? a : b
#define TRUE 1
#define FALSE 0
#define num_elem 20
static char rcsid[]="$Id: attrabbr.c,v 2.6 2002/04/23 16:46:41 prlao Exp $";
int checklen(int *, int *, int *, int *, char *, char *, char *, char *, char *);
int change(char *, char *, char *);
int numtimes(char *, char *);
char *trim(char *);
int verify(char *, char*);
int is_num(char);
void truncate_nonum (char *, char *, int );
int any_num (char* );
void attrabbr(char *text5, char *text8, char *text20, char *text40, char *text66,
int language)
{
int len;
char text81[82];
char text80[81];
char *khar = text80;
char text_save[81];
char *vowels = "AEIOUaeiou";
char *numbers = "0123456789";
char oldstr[num_elem][11];
char newstr[num_elem][11];
char word[20][25];
int i = 0;
int j = 0;
int k = 0;
int pos = 0;
int num_words = 0;
int num_letters = 0;
int num_mod = 0;
int done5 = FALSE;
int done8 = FALSE;
int done20 = FALSE;
int done40 = FALSE;
int cont_loop =1;
char tempstr[257];
int endofline = FALSE;
int num_str =0;
/* checklen is the "default" way to abbreviate the description. it will be called here
to see if it can succeed. if its not, there are other techniques to apply and then
checklen will be called again */
for(i=0;i<num_elem;i++)
{
memset((char *)newstr,'\0',11);
memset((char *)oldstr,'\0',11);
}
strcpy(text66,text66+verify(text66," ")-1); /* Strip leading spaces */
strcpy(text80,text66);
for (i=(int)strlen(text80)-1;*(text80+i) == ' ';i--)
*(text80+i) = '\0'; /* Strip trailing spaces */
if (checklen(&done5,&done8,&done20,&done40,text5,text8,text20,text40,text80)) return;
#ifdef PRINTFS
printf("1. checklen done:%ld, length:%ld, |%s|\n", done20, (int)strlen(text20), text20);
#endif
switch (language) {
case 1: /*ENGLISH COMMNON*/
case 2:
case 7:
case 8: /* English for France */
strcpy(oldstr[0], " W/");/* This appears to do nothing*/
strcpy(oldstr[1], "//");
strcpy(oldstr[2], "/");
strcpy(oldstr[3], "^");
strcpy(oldstr[4], "//");
strcpy(oldstr[5], " OR ");
strcpy(oldstr[6], "&");
strcpy(oldstr[7], " AND ");
strcpy(oldstr[8], " WITH ");
strcpy(oldstr[9], " WITHOUT ");
strcpy(oldstr[10], " W/ ");
strcpy(oldstr[11], " ");
strcpy(newstr[0], " W^");
strcpy(newstr[1], "^^");
strcpy(newstr[2], " / ");
strcpy(newstr[3], "/");
strcpy(newstr[4], " // ");
strcpy(newstr[5], " / ");
strcpy(newstr[6], " & ");
strcpy(newstr[7], " & ");
strcpy(newstr[8], " W/");
strcpy(newstr[9], " W/O ");
strcpy(newstr[10], " W/");
strcpy(newstr[11], " ");
num_str =12;
break;
case 3: /*FRENCH SPECIAL ABBREVIATION */
strcpy(oldstr[0], " //");
strcpy(oldstr[1], "/");
strcpy(oldstr[2], "^");
strcpy(oldstr[3], "//");
strcpy(oldstr[4], "|");
strcpy(oldstr[5], " OU ");
strcpy(oldstr[6], "&");
strcpy(oldstr[7], " ET ");
strcpy(oldstr[8], " AVEC ");
strcpy(oldstr[9], " NON ");
strcpy(oldstr[10], " ");
strcpy(newstr[0], " ^^");
strcpy(newstr[1], " / "); /* PAD SPACES */
strcpy(newstr[2], "/");
strcpy(newstr[3], " // "); /* PAD SPACES */
strcpy(newstr[4], " / ");
strcpy(newstr[5], " / "); /* OR */
strcpy(newstr[6], " & ");
strcpy(newstr[7], " & "); /* AND */
strcpy(newstr[8], " AV "); /* WITH */
strcpy(newstr[9], " N "); /* WITHOUT */
strcpy(newstr[10], " "); /* FIX DOUBLESPACES */
num_str =11;
break;
case 4: /* GERMAN */
strcpy(oldstr[0], " //");
strcpy(oldstr[1], "/");
strcpy(oldstr[2], "^");
strcpy(oldstr[3], "//");
strcpy(oldstr[4], "|");
strcpy(oldstr[5], " ODER ");
strcpy(oldstr[6], "&");
strcpy(oldstr[7], " UND ");
strcpy(oldstr[8], " ");
strcpy(newstr[0], " ^^");
strcpy(newstr[1], " / "); /* PAD SPACES */
strcpy(newstr[2], "/");
strcpy(newstr[3], " // "); /* PAD SPACES */
strcpy(newstr[4], " / ");
strcpy(newstr[5], " / "); /* OR */
strcpy(newstr[6], " & ");
strcpy(newstr[7], " & "); /* AND */
strcpy(newstr[8], " ");
num_str = 9;
break;
case 5:/* DUTCH */
strcpy(oldstr[0], " //");
strcpy(oldstr[1], "/");
strcpy(oldstr[2], "^");
strcpy(oldstr[3], "//");
strcpy(oldstr[4], "|");
strcpy(oldstr[5], " OF ");
strcpy(oldstr[6], "&");
strcpy(oldstr[7], " EN ");
strcpy(oldstr[8], " MET ");
strcpy(oldstr[9], " ZONDER ");
strcpy(oldstr[10], " ");
strcpy(newstr[0], " ^^");
strcpy(newstr[1], " / "); /* PAD SPACES */
strcpy(newstr[2], "/");
strcpy(newstr[3], " // "); /* PAD SPACES */
strcpy(newstr[4], " / ");
strcpy(newstr[5], " / "); /* OR */
strcpy(newstr[6], " & ");
strcpy(newstr[7], " & ") /* AND */;
strcpy(newstr[8], " M "); /* WITH , abbreviation is a guess */
strcpy(newstr[9], " Z "); /* WITHOUT, abbreviation is a guess */
strcpy(newstr[10], " ");
num_str =11;
break;
case 6:/* ITALIAN */
strcpy(oldstr[0], " //");
strcpy(oldstr[1], "/");
strcpy(oldstr[2], "^");
strcpy(oldstr[3], "//");
strcpy(oldstr[4], "|");
strcpy(oldstr[5], " O ");
strcpy(oldstr[6], "&");
strcpy(oldstr[7], " E ");
strcpy(oldstr[8], " CON ");
strcpy(oldstr[9], " SENZA ");
strcpy(oldstr[10], " ");
strcpy(newstr[0], " ^^");
strcpy(newstr[1], " / "); /* PAD SPACES */
strcpy(newstr[2], "/");
strcpy(newstr[3], " // "); /* PAD SPACES */
strcpy(newstr[4], " / ");
strcpy(newstr[5], " / "); /* OR */
strcpy(newstr[6], " & ");
strcpy(newstr[7], " & ") /* AND */;
strcpy(newstr[8], " CON "); /* WITH abbreviaion is a guess */
strcpy(newstr[9], " S/Z "); /* WITHOUT abbreviation is a guess */
strcpy(newstr[10], " ");
num_str =11;
break;
/*case 8:SPANISH , not Spanish anymore but English for France*/
case 9:
strcpy(oldstr[0], " //");
strcpy(oldstr[1], "/");
strcpy(oldstr[2], "^");
strcpy(oldstr[3], "//");
strcpy(oldstr[4], "|");
strcpy(oldstr[5], " O ");
strcpy(oldstr[6], "&");
strcpy(oldstr[7], " Y ");
strcpy(oldstr[8], " CON ");
strcpy(oldstr[9], " SIN ");
strcpy(oldstr[10], " ");
strcpy(newstr[0], " ^^");
strcpy(newstr[1], " / "); /* PAD SPACES */
strcpy(newstr[2], "/");
strcpy(newstr[3], " // "); /* PAD SPACES */
strcpy(newstr[4], " / ");
strcpy(newstr[5], " / "); /* OR */
strcpy(newstr[6], " & ");
strcpy(newstr[7], " & ") /* AND */;
strcpy(newstr[8], " CON "); /* WITH abbreviation is a guess */
strcpy(newstr[9], " SIN "); /* WITHOUT */
strcpy(newstr[10], " ");
num_str =11;
break;
default:
strcpy(oldstr[0], " //");
strcpy(oldstr[1], "/");
strcpy(oldstr[2], "^");
strcpy(oldstr[3], "//");
strcpy(oldstr[4], "|");
strcpy(oldstr[5], "&");
strcpy(oldstr[6], " ");
strcpy(newstr[0], " ^^");
strcpy(newstr[1], " / "); /* PAD SPACES */
strcpy(newstr[2], "/");
strcpy(newstr[3], " // "); /* PAD SPACES */
strcpy(newstr[4], " / ");
strcpy(newstr[5], " & ");
strcpy(newstr[6], " "); /* DELETE DOUBLE SPACE */
num_str =7;
break;
}
for (i=0;i<num_str;i++) {
if ((int)strlen(oldstr[i]) == 0) break;
j = change(text80,oldstr[i],newstr[i]);
if (checklen(&done5,&done8,&done20,&done40,text5,text8,text20,text40,text80)) return;
}
#ifdef PRINTFS
printf("2. convert chars done:%ld, length:%ld, |%s|\n", done40, (int)strlen(text40), text40);
#endif
for (i=(int)strlen(text80)-1;i>=1;i--) {
tempstr[0] = khar[i];
tempstr[1] = '\0';
if ((verify(tempstr,vowels) == 0 && khar[i-1] != ' ') ||
(khar[i] == khar[i-1] && khar[i] != '/' &&
verify(tempstr,numbers) > 0)) {
strcpy(text80+i,text80+i+1);
if (checklen(&done5,&done8,&done20,&done40,text5,text8,text20,text40,text80))
return;
}
}
#ifdef PRINTFS
printf("3. vowels done:%ld, length:%ld, |%s|\n", done20, (int)strlen(text20), text20);
printf("3. vowels done:%ld, length:%ld, |%s|\n", done40, (int)strlen(text40), text40);
#endif
strcpy(text_save,text80);
while (cont_loop) {
num_words++;
j = strstr(text80," ") - text80 + 1;
if (j < 0) {
j = (int)strlen(text80)+1;
endofline = TRUE;
}
if (j > 0) {
memset(word[num_words],0,25);
strncpy(word[num_words],text80,j-1);
*(word[num_words]+(j-1)) = '\0';
if (strcmp(word[num_words],"W/") == 0 ||
strcmp(word[num_words],"IN") == 0 ||
strcmp(word[num_words],"/") == 0 ||
strcmp(word[num_words],"//") == 0 ||
strcmp(word[num_words],"+") == 0 ||
strcmp(word[num_words],"|") == 0 ||
strcmp(word[num_words],"AV") == 0)
{
num_words--;
}
else if ((int)strlen(word[num_words]) > 1 &&
strncmp(word[num_words],"W/",2) == 0)
{
strncpy(word[num_words],word[num_words],3);
*(word[num_words]+3) = '\0';
}
strcpy(text80, text80+j);
}
if (endofline == TRUE) break;
}
#ifdef PRINTFS
printf("4. Removing abbreviation done:%ld, length:%ld, |%s|\n", done20, (int)strlen(text20), text20);
printf("4. Removing abbreviation done:%ld, length:%ld, |%s|\n", done40, (int)strlen(text40), text40);
#endif
/* getting the first "num_letters" letters from each words */
if (done8 == FALSE) {
num_letters = MAX(8/num_words,1);
num_mod = 8 % num_words;
if (num_mod > 0)
num_letters++;
pos = 0;
for (i=1;i <= num_words;i++) {
if (any_num(word[i])) {
/* the words that contain numbers can not be concat */
if (8-pos >= (int)strlen(word[i])) {
strncpy(text8+pos,word[i],(int)strlen(word[i]));
pos += (int)strlen(word[i]);
}
}
else if ((int)strlen(word[i]) > num_letters) {
/* if the word is longer than the "num_letters" then truncate and concat and fit*/
strncpy(text8+pos,word[i],MIN(num_letters,8-pos));
pos += num_letters;
}
else {
/* if the word is shorter than the "num_letters" then concat and fit*/
strncpy(text8+pos,word[i],MIN((int)strlen(word[i]),8-pos));
pos += (int)strlen(word[i]);
}
if (pos > 7) break;
}
text8[MIN(pos,8)] = '\0';
}
/* last effort to make 5? */
if (done5 == FALSE) {
num_letters = MAX(5/num_words,1);
num_mod = 5 % num_words;
if (num_mod > 0) num_letters++;
pos=0;
for (i=1;i <= num_words;i++) {
if (any_num(word[i])) {
if (5-pos >= (int)strlen(word[i])) {
strncpy(text5+pos,word[i],(int)strlen(word[i]));
pos += (int)strlen(word[i]);
}
}
else if ((int)strlen(word[i]) > num_letters) {
/* if the word is longer than the "num_letters" then truncate and concat and fit*/
strncpy(text5+pos,word[i],MIN(num_letters,5-pos));
pos += num_letters;
}
else {
strncpy(text5+pos,word[i],MIN((int)strlen(word[i]),5-pos));
pos += (int)strlen(word[i]);
}
if (pos > 4) break;
}
text5[MIN(pos,5)] = '\0';
}
/* last effort to make 20 */
if (done20 == FALSE) {
len = (int)strlen(text80);
strcpy(text80, text_save);
/* checklen will strip those out, so we will assume those are not here */
k = (int)strlen(text80) - (numtimes(text80," | ") * 2)
- (numtimes(text80," / ") * 2)
- (numtimes(text80," + ") * 2)
- (numtimes(text80," // ") * 2);
/* no idea whats this doing */
j = (20/(k-20));
for (i = len-1;i>=1;i-=j) {
if (khar[i] == ' ' || khar[i-1] == ' ' ||
(khar[i+1] == ' ' && khar[i-2] == ' ') ||
(khar[i-1] == ' ' && khar[i+2] == ' ') ||
(khar[i+1] == ' ' && khar[i-1] == ' ')) {
i += j-1;
continue;
}
/* protect from making numbers disappear */
if (!is_num(*(text80+i))) strcpy(text80+i,text80+i+1); else break;
if (checklen(&done5,&done8,&done20,&done40,text5,text8,text20,text40,text80))
return;
if (done20 == TRUE) break;
}
}
if (done20 == FALSE) {
truncate_nonum(text80, text20, 20);
}
if (done40 == FALSE) {
len = (int)strlen(text80);
strcpy(text80, text_save);
k = (int)strlen(text80) - (numtimes(text80," | ") * 2)
- (numtimes(text80," / ") * 2)
- (numtimes(text80," + ") * 2)
- (numtimes(text80," // ") * 2);
j = (33/(k-33));
for (i = len-1;i>=1;i-=j) {
if (khar[i] == ' ' || khar[i-1] == ' ' ||
(khar[i+1] == ' ' && khar[i-2] == ' ') ||
(khar[i-1] == ' ' && khar[i+2] == ' ') ||
(khar[i+1] == ' ' && khar[i-1] == ' ')) {
i += j-1;
continue;
}
strcpy(text80+i,text80+i+1);
/* protect from making numbers disappear */
if (!is_num(*(text80+i))) strcpy(text80+i,text80+i+1); else break;
if (checklen(&done5,&done8,&done20,&done40,text5,text8,text20,text40,text80))
return;
if (done40 == TRUE) break;
}
}
if (done40 == FALSE) {
truncate_nonum(text80, text40, 33);
}
return;
}
int checklen(int *done5, int *done8, int *done20, int *done40, char *text5,
char *text8, char *text20, char *text40, char *text80) {
int i = 0;
char temp[81];
char tempstr[257];
char jimstr[257];
if (*done40 == FALSE) {
/* if smaller than 33 already, just copy it */
if ((int)strlen(text80) <= 33) {
strcpy(text40,text80);
*done40 = TRUE;
}
/* if, after stripped of the spaces between / | + and //, its less than 33, then strip and copy */
else if (((int)strlen(text80) - (numtimes(text80," / ") * 2)
- (numtimes(text80," | ") * 2)
- (numtimes(text80," + ") * 2)
- (numtimes(text80," // ") * 2)) <= 33) {
strcpy(temp,text80);
i = change(temp, " / ", "/");
i = change(temp, " | ","|");
i = change(temp, " + ","+");
i = change(temp, " // ","//");
strcpy(text40,temp);
*done40 = TRUE;
}
}
/* exact same thing as 40 */
if (*done20 == FALSE) {
if ((int)strlen(text80) <= 20) {
strcpy(text20,text80);
*done20 = TRUE;
}
else if (((int)strlen(text80) - (numtimes(text80," / ") * 2)
- (numtimes(text80," | ") * 2)
- (numtimes(text80," + ") * 2)
- (numtimes(text80," // ") * 2)) <= 20) {
strcpy(temp,text80);
i = change(temp, " / ", "/");
i = change(temp, " | ","|");
i = change(temp, " + ","+");
i = change(temp, " // ","//");
strcpy(text20,temp);
*done20 = TRUE;
}
}
if (*done8 == FALSE) {
if ((int)strlen(text80) <= 8) {
strcpy(text8,text80);
*done8 = TRUE;
}
strncpy(tempstr,text80,5);
*(tempstr+5) = '\0';
if ((int)strlen(text80) - numtimes(tempstr," ") <= 8) {
strcpy(temp,text80);
i = change(temp," ","");
strncpy(text8,temp,8);
*(text8+8) = '\0';
*done8 = TRUE;
}
}
if (*done5 == FALSE) {
if ((int)strlen(text80) <= 5) {
strcpy(text5,trim(text80));
*done5 = TRUE;
}
strncpy(tempstr,text80,5);
*(tempstr+5) = '\0';
if ((int)strlen(text80) - numtimes(tempstr," ") <= 5) {
strcpy(temp, text80);
i = change(temp," ","");
strcpy(text5,trim(temp));
*done5 = TRUE;
}
}
if (*done5 == TRUE && *done8 == TRUE && *done20 == TRUE)
return(TRUE);
else
return(FALSE);
}
int numtimes(char *str, char *arg) {
int arglen;
int x;
int savex = 0;
int num_times = 0;
int i = 0;
arglen = (int)strlen(arg);
x = strstr(str, arg) - str;
while (x >= savex) {
num_times++;
savex = x + arglen;
if (savex > (int)strlen(str))
break;
x = (int) strstr(str+savex,arg) + savex - 1;
}
return (num_times);
}
int change(char *str, char *arg1, char *arg2) {
int len = 0;
int num_changes = 0;
int i = 0;
int anchor = 0;
long pos = 0;
int num_times = 0;
char tempstr[257];
int cont_loop=1;
while (cont_loop) {
pos = (strstr(str+anchor,arg1)-(str+anchor)) + anchor;
if (strstr(str+anchor,arg1) == NULL) pos = -1;
if (pos >= anchor) {
/* if ((strcmp(arg1," ") == 0) && (strcmp(arg2," ") == 0)) {
if (strcmp(str+pos," ") == 0)
break;
}
*/
num_times++;
strncpy(tempstr,str,pos);
*(tempstr+pos) = '\0';
strcat(tempstr,arg2);
strcat(tempstr,str+pos+(int)strlen(arg1));
strcpy(str,tempstr);
anchor = pos + (int)strlen(arg2);
}
else {
break;
}
}
return(num_times);
}
char *trim(char *text) {
char *tempstr = text;
tempstr += (int)strlen(tempstr);
while(*(--tempstr) == ' ')
;
*(++tempstr) = '\0';
return(text);
}
/* strange little function
arg2 is the string where the search will be performed
arg1 is a string of characters to be searched, e.g. arg1 is a list of vowels (aeiou)
for each character in arg1, find its first occurence in arg2
if not found, return the position of this character in arg1 (so if it's an 'i', this func returns 3)
if found, get the next character from arg1 and repeat this
why? don't ask. i'm just documenting
*/
int verify(char *arg1, char *arg2) {
char *testchar = arg1;
while (*testchar != '\0') {
if (strchr(arg2,*testchar) == 0)
return((testchar - arg1) + 1);
testchar++;
}
return(0);
}
int is_num(char a) {
if ((a>='0') && (a<='9')) return TRUE; else return FALSE;
}
/* source is the original string
target is the output placement var
trunc len is the length of target
this is going to do the usual truncate, the difference is in that if the truncation
ended up splitting a number, it will remove the whole number.
if the whole thing is a number, then a normal truncation is performed - nothing
we can do about it right?
*/
void truncate_nonum (char *source, char *final_target, int trunc_len) {
int trunc_ptr=0;
char *target;
target=(char*)malloc((int)strlen(source) + 1);
strcpy(target, source);
if (is_num(*(target+trunc_len))) { /* if this is a number.. */
/* find the closest non-number */
trunc_ptr=trunc_len-1;
while (is_num(*(target+trunc_ptr)) && trunc_ptr >= 0) trunc_ptr--;
if (trunc_ptr<0) /* if everyhing is number... */
strncpy(target,source,trunc_len);
else
*(target+trunc_ptr+1) = '\0';
} else *(target+trunc_len) = '\0';
if ((int)strlen(target)>trunc_len) printf("WARNING - truncate_nonum doesn't truncate enough\n");
strncpy(final_target,target,(int)strlen(target));
}
int any_num (char* text) {
int i,stat;
for (i=0; i<(int)strlen(text); i++)
if (!is_num(*(text+i)))
return FALSE;
return TRUE;
}