Quantcast
Channel: UNIX and Linux Forums
Viewing all articles
Browse latest Browse all 16232

C code doubt

$
0
0
hi all, I am not a C expert. can you tell me what does the below C program does.

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;

}


Viewing all articles
Browse latest Browse all 16232

Latest Images

Trending Articles



Latest Images