/* This program formats C files *//* See CFORMAT.TXT for a detailed explanation of what if does *//* */#define PAD 2 /* number of spaces to indent after a "$(" */#define SPACE 32#define TAB 127#define EOL 155int iocb,count,i,length,csflag,dflag,iocb2;char s[20],c,lastchar,nextchar,*bufptr,*endptr,bak[20];main() $(  int backup;  char *maxsize,*address; /* address MUST be the last variable defined!!! */  address=&address+100; /* This is the address for the text */  maxsize=0xBC00-address; /* Maximum text length */  printf("\f\t   The ACE C Formatter\n\t   by Ralph Walden\n\n");  printf("^M will insert a return\n^N will delete through the next return\n\n");  while(1) $( /* loop until user indicates no more files via getname() function */    dflag=csflag=iocb=count=lastchar=c=backup=0;    slow();    getname(s);    printf("Do you want a back-up? (Y/N)");    if(tolower(getkey())=='y') backup=1;    putchar('\n');    fast();    closeall();    strcpy(bak,s);    normalize(s,"C");    if(backup) $(      if(i=find(bak,strlen(bak),'.')) *(bak+i)=0; /* erase the period */      normalize(bak,"BAK");      printf("\u%s <<< %s\n\n",s,bak);    $)    else printf("\u%s  (no back-up)\n\n",s);    if((iocb=copen(s,'r'))<1) $(      printf("Can't open %s\n",s);      continue;    $)    length=bgets(address,maxsize,iocb); /* read in all of the text *//* address points to the stack, to which was added a safety margin of 100 *//* This gives us an area for the buffer.  address MUST be the last variable defined! */    close(iocb);    if(length>=maxsize) $(      printf("Text exceeds %dK\nYou wouldn't be able to link\nit either!\n",length/1024);      continue;    $)    if(backup) $(      if((iocb2=copen(bak,'w'))>0) $(        bputs(address,length,iocb2); /* write all of the text to a backup */        close(iocb2);      $)      else $(        printf("I can't open %s\nShall I continue without a back-up?\n(Y/N)",bak);        if(toupper(getkey())!='Y') continue;      $)    $)    endptr=address+length; /* get the length of the text */    *(endptr+1)=EOL; /* to avoid some checks for end of buffer */    if((iocb=copen(s,'w'))<0) $(      printf("Can't open %s\n",s);      continue;    $)    bufptr=address;    while((i=find(address,length,TAB))>=0) *(bufptr+i)=SPACE; /* convert tabs to spaces */    while(*bufptr==SPACE) ++bufptr; /* remove any starting spaces */    for(;bufptr<endptr;++bufptr) $( /* MAIN LOOP */      while(((c=*bufptr)>'d') && (c != EOL)) out(*bufptr++);      if(c==13) c=EOL; /* convert control M to a RETURN */      switch(c) $(        case SPACE: /* remove all but one space */          out(SPACE);          while(*bufptr==SPACE) ++bufptr;          --bufptr; /* in order to read next character */          break;        case 'b': /* handles "break" statements */          if(match(bufptr,"break;")) $(            if(dflag) $( /* break after a default */              count-=PAD;              csflag=dflag=0;            $)            else if(csflag) $( /* break after a case */              count-=PAD;              csflag=0;            $)          $)          out(c);          break;        case 'c': /* handles "case" statement */          if(match(bufptr,"case ")) $(            csflag=1; /* indicate we are dealing with a case */            count+=PAD; /* increase the indentation */          $)          out(c);          break;        case 'd': /* handles "default" statement */          if(match(bufptr,"default")) $(            ++dflag; /* indicate that we have a default */            count+=PAD;          $)          out(c);          break;        case '0': /* convert all hex to upper case */          out(c);          if(tolower(*(bufptr+1))=='x') $(            out(*(bufptr+1));            bufptr+=2;            while(hex(*bufptr)) out(toupper(*bufptr++));            --bufptr; /* so we will read it at top of loop */          $)          break;        case '$': /* this handles $( and $) */          nextchar= *(bufptr+1);          lastchar= *(bufptr-1);          if(nextchar=='(') $(            if((lastchar != SPACE) && (lastchar != EOL) && (*(bufptr-2) != EOL)) out(SPACE); /* add a space */            count+=PAD;          $)          out(c);          if(nextchar==')') count-=PAD;          break;        case '&': /* separate || and && with spaces */        case '|':          lastchar= *(bufptr-1);          if(lastchar==c) $(            out(c);            if(*(bufptr+1)!=SPACE) out(SPACE);          $)          else if((*(bufptr+1)==c) && (lastchar!=SPACE)) $(            out(SPACE);            out(c);          $)          else out(c);          break;        case '/': /* this handles comments */          if(*(bufptr+1)=='*') $(            out(*bufptr++); /* '/' */            out(*bufptr++); /* '*' */            while(1) $( /* find the end of the comment */              while((*bufptr != EOL) && (*bufptr != '*')) $(                out(*bufptr++);              $)              out(*bufptr);              if(*bufptr == EOL) $( /* if the comment continues to the next line, we must add a '/*' */                i=1;                while(*(bufptr+i)==SPACE) ++i;                if(*(bufptr+i) != '/') $(                  out('/'); /* start the new line with a comment it it isn't already there */                  out('*');                  out(SPACE);                $)              $)              else if(*(bufptr+1)=='/') break; /* end of comment */              ++bufptr; /* not the end of the comment, so we continue the loop */            $)          $)          else out(c);          break;        case EOL: /* this handles all returns */          out(c);          if((bufptr+2)<endptr) $(            ++bufptr;            while(*bufptr==SPACE) ++bufptr;            if(csflag) $(              if((match(bufptr,"case ")) || (match(bufptr,"default"))) count-=PAD;            $)            i=0; /* adjust the padding according to "case", "default", etc. */            if((*bufptr=='$') && (*(bufptr+1)==')')) i=2; /* back up two spaces for statement close */            if(*bufptr=='/') i=count; /* don't add spaces if it's a comment line */            if(match(bufptr,"asm ")) i-=2; /* indent two spaces */            for(;i<count;++i) out(SPACE); /* send out the appropriate number of spaces */            --bufptr;          $)          break;        case '"': /* handles quotes */          out(c);          ++bufptr;          while((*bufptr != '"') && (*bufptr != EOL)) out(*bufptr++);          if(*bufptr == EOL) $(            --bufptr;            break;          $)          out(*bufptr); /* end of quote */          break;        case 14: /* control N will delete through the next return */          while(*bufptr != EOL) ++bufptr;          break;        default :          out(c);          break;      $)    $)  $)  slow();  exit();$)out(tc)char tc;$(  cputc(tc,iocb);$)hex(c) /* determine if c is a hexadecimal character or not */char c;$(  if((c>='0' && c<='9') || (tolower(c)>='a' && tolower(c)<='f')) return 1;  else return 0;$)