A LINE EDITOR : MYWORD

 

ÀÛ¼º: ±èÁøÈ«

 

1Çг⠻õ³»±â¶§ C·Î óÀ½ ¸¸µé¾îº» ÇÁ·Î±×·¥ÀÓ. µµ½ºÀÇ edline°ú À¯»çÇÑ ±â´ÉÀ» ±¸ÇöÇÑ´Ù.

 

»ç¿ë¹ýÀº ¹Ù·Î ¾Æ·¡ comment¿¡ ÀÖÀ½.

 

 

/*

                                                                                              MYWORD4

 

 

             COMMANDS:

 

                          L                          : display the list

                          Q                          : quit

                          C [# or '.']    : change one line

                          P [# or '.']    : set current position

                          I [# or '.']    : insert oneline

                          D [# or '.']    : delete oneline

                          S [# or '.']    : substitute

                                                                                Ex)     "How can I help you? s ."

                                                                                                          "abc/defg"

                                                                                result: The string "abc" in line

                                                                                                          of the current position is

                                                                                                          replaced with "defg".

 

 

                          # means a number from 1 to NBRLINES

                          '.' means current position

*/

 

 

#include <stdio.h>

 

#define NBRLINES              200

#define LINELENGTH             100

#define TRUE               1

#define FALSE                           0

 

/* defines command messages */

#define MSG_NONE              0

#define MSG_LIST              1

#define MSG_QUIT              2

#define MSG_CHANGE             3

#define MSG_DESTROY         4      /* MSG_DESTROY informs to exit the program */

#define MSG_SETPOS      5

#define MSG_INSERT      6

#define MSG_DELETE      7

#define MSG_SUBSTITUTE  8

 

/* defines error messages */

#define MSG_UNKNOWN           100    /* MSG_UNKNOWN means unknown command */

#define MSG_OUTOFRANGE    101

 

 

struct TextStruct {

  char line[LINELENGTH];

  int  used;         /* mark the line if occupied */

};

 

struct TextStruct Text[NBRLINES];

struct TextStruct *LineP[NBRLINES];             /* Line Pointers */

int   TLines             =             0;                                   /* Total lines */

int   TChars             =             0;                                   /* Total chars */

int   MESSAGE             =             MSG_NONE;

int   POSITION  =       0;

 

void readfile(char *fname);

int getoneline(char *buf);

char upcase(char c);

void getcommand(char *buf);

void list(void);

void quit(char *fname);

void savefile(char *fname);

void changeline(char *buf);

void postmessage(int msg);

int val(char *str);

int power10(int num);

void clearline(char *);

void setposition(char *buf);

int getposition(char *buf);

void insertline(char *buf);

void deleteline(char *buf);

void process_error(void);  /* process error messages */

int findemptyline();

int str_cmp(char *src1, char *src2);

int str_len(char *str);

void str_cpy(char *dst, char *src);

int getpara(int idx, char *argvs, char *out);

void readsomestr(char *src, char *buf, int idx, int cnt);

void substitute(char *buf);

 

 

void main(int argc, char **argv)

{

  char buf[LINELENGTH];                           /* temporary line-buffer */

 

  if (argc != 2) {

             printf("Usage: %s filename\n", argv[0]);

             return;

  }

 

  readfile(argv[1]);                    /* read file into the Text[] */

 

  while (MESSAGE != MSG_DESTROY) {

             printf("How can I help you? ");               /* the PROMPT */

             getoneline(buf);                             /* read one line from console */

             getcommand(buf);                                           /* distinguish commands */

 

             switch(MESSAGE) {

                         case MSG_LIST:list();                        break;

                         case MSG_QUIT:quit(argv[1]);                           break;

                         case MSG_CHANGE:changeline(buf);            break;

                         case MSG_SETPOS:setposition(buf);           break;

                         case MSG_INSERT:insertline(buf);               break;

                         case MSG_DELETE:deleteline(buf);              break;

                         case MSG_SUBSTITUTE:substitute(buf);      break;

             }

 

        process_error();

 

             clearline(buf);              /* clear the 'buf' */

  }

}

 

 

/* read data from a file into the 'Text' array. */

void readfile(char *fname)

{

  FILE *handle;

  char c;

  int cnt;

 

  /* initialize the line pointers */

  for (cnt=0; cnt<NBRLINES; cnt++) {

             LineP[cnt]=&Text[cnt];       /* pointers indicate each line of the Text */

             LineP[cnt]->used=FALSE;

  }

 

 

  /* if the file is not exist, create new file */

  if ((handle=fopen(fname, "rt")) == NULL) {

             printf("\"%s\" new file.\n", fname);

             return;

  }

 

  cnt=0;

  while ((c=fgetc(handle)) != EOF) {

 

             if (c != '\n' && cnt < LINELENGTH-1) {

                                       LineP[TLines]->line[cnt]=c;     /* read a character */

                                       cnt++;

                                       TChars++;

             } else {

                                       LineP[TLines]->line[cnt]='\0';  /* make a string */

                                                                              LineP[TLines]->used=TRUE;

                                       cnt=0;

 

                                       if (TLines < NBRLINES) TLines++;

             }

 

             if (TLines == NBRLINES) break;

  }

 

  printf("\"%s\" opened %d chars / %d lines.\n", fname, TChars, TLines);

 

  POSITION=TLines;            /* default position value */

  fclose(handle);

}

 

int getoneline(char *buf)

{

  char c;

  int cnt=0;

 

  while((c=getchar()) != '\n') {

             if (cnt < LINELENGTH-1) cnt++;

             else break;

 

             *buf++ = c;

  }

 

  *buf='\0';     /* make a string */

 

  return cnt;

}

 

char upcase(char c) /* changes lowercase letters to capital letters */

{

  if (c >= 'a' && c <= 'z') return c-32;

  else return c;

}

 

/* make a message for main function */

void postmessage(int msg)

{

  MESSAGE=msg;

}

 

/* retrieve a command */

void getcommand(char *buf)

{

  switch (upcase(*buf)) {

             case 'L':postmessage(MSG_LIST); break;

             case 'Q':postmessage(MSG_QUIT); break;

             case 'C':postmessage(MSG_CHANGE); break;

             case '\0':postmessage(MSG_NONE); break;

             case 'P':postmessage(MSG_SETPOS); break;

             case 'I':postmessage(MSG_INSERT); break;

             case 'D':postmessage(MSG_DELETE); break;

             case 'S':postmessage(MSG_SUBSTITUTE); break;

             default :postmessage(MSG_UNKNOWN); break;

  }

}

 

/* display all of the list */

void list()

{

  int t;

 

  for (t=0; t<TLines; t++)

             printf("%d: %s\n", t+1, LineP[t]->line);

}

 

void quit(char *fname)

{

  char c;

 

  printf("save changes(y/n) ");

 

  c=upcase(getchar());

 

  if (c == 'Y') {

             savefile(fname);

             printf("write\n");

             postmessage(MSG_DESTROY);       /* ends program */

  } else

             if (c == 'N') {

               printf("exit\n");

               postmessage(MSG_DESTROY);

             }

 

  /* clear the key buffer */

  if (c != '\n') while ((c=getchar()) != '\n');

}

 

void savefile(char *fname)

{

  FILE *handle;

  int t, i;

 

  handle=fopen(fname, "wt"); /* create a file(overwrite) */

 

  for (t=0; t<TLines; t++) {

             for (i=0; LineP[t]->line[i] != '\0'; i++)

                          fputc(LineP[t]->line[i], handle);

             fputc('\n', handle);     /* make a newline */

  }

 

  fclose(handle);

}

 

/* return a parameter(number) */

int getposition(char *buf)

{

  if (*(buf+2) == '.') return(POSITION);  /* current position number */

  else return(val(buf+2));                /* read number */

}

 

void changeline(char *buf)

{

  char tmp[LINELENGTH];

  int theline;

 

  theline=getposition(buf);

 

  if (theline < 1 || (TLines == 0 && theline > TLines+1) ||

     (TLines != 0 && theline > TLines)) {

        if (theline == -1) postmessage(MSG_UNKNOWN); /* NO PARAMETER!! */

             else postmessage(MSG_OUTOFRANGE);            /* OUT OF RANGE!! */

           return;

  }

 

  printf("%d ", theline);

 

  if (getoneline(tmp) == 0) return; /* if nothing is input */

 

  str_cpy(LineP[theline-1]->line, tmp);

  LineP[theline-1]->used=TRUE;

 

  if (theline == 1 && TLines == 0) {

    POSITION++;

    if (TLines < NBRLINES) TLines++; /* correct the total line(TLines) */

  }

}

 

void str_cpy(char *dst, char *src)

{

  while (*dst++=*src++);

}

 

/* translate a string to number */

int val(char *str)

{

  char numstr[5];

  int cnt=0, t;

  int theval=0;

 

  while(*str >= '0' && *str <='9' && cnt<4) {

    numstr[cnt]=*str;

    str++;

    cnt++;

  }

 

  if (cnt==0) return -1;   /* number wasn't input */

 

  numstr[cnt]='\0';        /* make it a string */

 

  for(t=0; t<cnt; t++)

    theval += (numstr[t]-'0')*power10(cnt-t-1);

 

  return theval;

}

 

/* make the power of 10 */

int power10(int num)

{

  int t;

  int theval=1;

 

  for (t=0; t<num; t++) theval *= 10;

 

  return theval;

}

 

/* clear the line buffer */

void clearline(char *buf)

{

  int t;

 

  for(t=0; t<LINELENGTH; t++) *(buf+t)='\0';

}

 

void setposition(char *buf)

{

  int theline;

 

  if (*(buf+2) == '.') {

    printf("current line number = %d\n", POSITION);

    return;

  }

 

  theline=val(buf+2);          /* read number */

 

  if (theline < 1 || theline > TLines) {

     if (theline == -1) postmessage(MSG_UNKNOWN);

     else postmessage(MSG_OUTOFRANGE);

     return;

  }

 

  POSITION=theline;

  printf("moved to line number %d\n", POSITION);

}

 

void deleteline(char *buf)

{

  int t, theline;

 

  theline=getposition(buf);

 

  if (theline < 1 || theline > TLines) {

        if (theline == -1) postmessage(MSG_UNKNOWN);

           else postmessage(MSG_OUTOFRANGE);

                          return;

  }

 

  /* mark it to NOT-USED */

  LineP[theline-1]->used=FALSE;

 

  /* move up line pointers */

  for (t=theline-1; t<TLines-1; t++) LineP[t]=LineP[t+1];

 

  if (TLines > 0) TLines--;

  if (POSITION > TLines) POSITION=TLines; /* correct POSITION */

}

 

void insertline(char *buf)

{

  char tmp[LINELENGTH];

  int t, emptyline;

  int theline;

 

  theline=getposition(buf);

 

  if (theline < 1 || theline > TLines) {

        if (theline == -1) postmessage(MSG_UNKNOWN);

           else postmessage(MSG_OUTOFRANGE);

           return;

  }

 

  if (theline == NBRLINES) printf("%d ", theline);

  else printf("%d ", theline+1);

 

  if (getoneline(tmp) == 0) return;  /* if nothing is input */

  if (TLines < NBRLINES) TLines++;

 

  /* move down line pointers */

  for (t=TLines; t>theline; t--) LineP[t-1]=LineP[t-2];

 

  if ((emptyline=findemptyline()) == -1) emptyline=NBRLINES-1;

  str_cpy(Text[emptyline].line, tmp);

 

  LineP[theline]=&Text[emptyline];

  LineP[theline]->used=TRUE;

}

 

int findemptyline()

{

  int t;

 

  /* find a empty line */

  for (t=0; t<NBRLINES; t++)

    if (Text[t].used == FALSE) return t;

 

  return -1; /* no empty line found */

}

 

void process_error()

{

  switch (MESSAGE) {

    case MSG_OUTOFRANGE:

                 printf("requested line number out of range!\n");

                          break;

             case MSG_UNKNOWN:

                          printf("error\n");

                          break;

  }

}

 

int getpara(int idx, char *argvs, char *out)

{

   int t=0, i=0;

   int cnt=0;

   char c;

 

   if (*argvs == '\0') return 0;               /* if nothing is input */

   *out='\0';                                                              /* clean up */

 

   while (*(argvs+t)) {

              if (*(argvs+t) == '/') cnt++;

 

              if (cnt == idx) {

                if (idx > 0) t++;

 

                while (1) {

                           c=*(argvs+t+i);

                           if (c == '/' || c == '\0') break;

                           *(out+i)=c;

                           i++;

                }

 

                *(out+i)='\0';

 

                return 1;

              }

 

              t++;

   }

 

   return 0;

}

 

void readsomestr(char *src, char *buf, int idx, int cnt)

{

  int t;

 

  for (t=0; t<cnt; t++) *(buf+t)=*(src+t+idx);

  *(buf+t)='\0';  /* make it a string */

}

 

int str_cmp(char *src1, char *src2)

{

  int t=0;

 

  while(1) {

             if (*(src1+t) != *(src2+t)) return 0;

             if (*(src1+t) == '\0' && *(src2+t) == '\0') break;

 

             t++;

  }

 

  return 1;

}

 

int str_len(char *str)

{

  int t=0;

 

  while(*(str+t)) t++;

 

  return(t);

}

 

void substitute(char *buf)

{

  char tmp[LINELENGTH];

  char src1[30], src2[30], tmp2[30];

  int theline, len1, len2;

  int pos1=0, pos2=0, cnt=0, found=FALSE;

 

  theline=getposition(buf);

 

  if (theline < 1 || theline > TLines) {

                          if (theline == -1) postmessage(MSG_UNKNOWN);

                          else postmessage(MSG_OUTOFRANGE);

                          return;

  }

 

  if (getoneline(tmp) == 0) {    /* if nothing is input */

             postmessage(MSG_UNKNOWN);

             return;

  }

 

  /* if nothing is input for 1st parameter, make error */

  if (getpara(0, tmp, src1) == FALSE) {

             postmessage(MSG_UNKNOWN);

             return;

  }

  /* if nothing is input for 2nd parameter, make error */

  if (getpara(1, tmp, src2) == FALSE) {

             postmessage(MSG_UNKNOWN);

             return;

  }

 

  /* if the first and the second parameter are same... */

  if (str_cmp(src1, src2)) return;

 

  len1=str_len(src1);

  len2=str_len(src2);

 

  while(1) {

             if ((found == FALSE) && (LineP[theline-1]->line[pos1] == *src1)) {

               readsomestr(LineP[theline-1]->line, tmp2, pos1, len1);

               if (str_cmp(src1, tmp2)) {

                          cnt=len2;

                          pos1+=len1;

                          found=TRUE;

               }

             }

 

             if (found == FALSE) tmp[pos2] = LineP[theline-1]->line[pos1];

             else {

               if (pos2 == 100) break;

 

               if (*src2 != '\0') {

                          tmp[pos2] = *(src2+(len2-cnt));

                          cnt--;

                          pos2++;

               }

 

               if (cnt == 0) found=FALSE;

               continue;

             }

 

             pos1++;

             pos2++;

 

             if (LineP[theline-1]->line[pos1] == '\0') break;

  }

 

  tmp[pos2]='\0';                       /* make a string */

  /* copy the completed temporary block 'tmp' to original block of 'Text' */

  str_cpy(LineP[theline-1]->line, tmp);

}