Hey guys-
I have to write a program in C, a pretty printer, that will be used in formatting assembly language code. To run the input, a source file must be provided as input for the 1st argument. A 2nd runtime argument is optional and, if present, it must be a non-negative integer that indicates the number of extra blanks to be placed between columns in the resultant output. For those of you unfamiliar, an assembly language file might look like this:

SENT:                     .WORD         0                ; Initializes the sentinel as 0...
pArray:                   .BLOCK        20             ; Reserves space  ...                   
nArray:                   .BLOCK        20             ; Reserves space for 10 ...
indexP:                   .WORD         0                ; Index Register value for ...

It might be hard to see, but there are four columns, so if one were to write the program without the columns, my program will add evenly spaced columns.
The pretty printer must take any valid assembly language source program as input and produce as output the same source program in a more readable form. Specifically, the “columns for the label, operand, operands, and comment fields are to be neatly aligned.
Here is what I have so far:

#define LIMIT 100
#define NL '\n'
#define NC '\0'
#define BC ' '
 
replace (char s[], char Old, char New) {
int i;
for(i=0; s[i]!=NC; i++) {
if(s[i] == Old) {
s[i] = New;
}
}
}
 
trim(char s[]) {
int n = length(s);
int d = 0;
int i = 0;
while ((n>0) && (s[n-1]==BC)) {
s[n-1] = NC;
n = n - 1;
}
 
while((d < n) && (s[d]==BC)) {
d = d + 1;
}
if(d > 0) {
while(s[i+d] != NC) {
s[i] = s[i+d];
i = i + 1;
}
s[i] = NC;
}
}
 
readstring(char s[]) {
char next;
int i = 0;
scanf("%c",&next);
while(next != NL) {
s[i] = next;
i = i + 1;
scanf("%c",&next);
}
s[i] = NC;
}
 
int length(char s[]) {
int i=0;
while(s[i]!= NC) {
i = i + 1;
}
return i;
}
 
int indexOf(char S[], char IT[]) {
int result = -1;
int n=length(S);
int k=length(IT);
int i, j;
if(k > 0) {
i=0;
while((result < 0) && (i<(n-k))) {
for(j=0; (j<k)&&(S[i+j]==IT[j]); j++) {
}
if(j<k) {
i=i+1;
} else {
result=i;
}
}
}
return result;
}
 
void substring(char S[], int start, int len, char Result[]) {
int i=0;
if((start >= 0) && ((start+len) <= length(S))) {
while(i < len) {
Result[i] = S[start+i];
i = i + 1;
}
}
Result[i] = NC;
}
 
char charAt(char S[], int i) {
char result = NC;
if(i < length(S)) {
result = S[i];
}
return result;
}
 
printstring(char s[]) {
int i=0;
printf("{");
while(s[i] != NC) {
printf("%c",s[i]);
i = i + 1;
}
printf("}");
}
 
printstringln(char s[]) {
printstring(s);
printf("%c",NL);
}

I am not sure what other methods I need to add to make this work. Can anyone help me make them? Thanks!

Comments
Keep up the good work

It's a pity you didn't format your C code while you were at it :rolleyes:

Where's all the indentation to denote block structure, and blank lines to separate one function from another?

If you are writng a C program, use fgets() to get the string from the keyboard because it will not permit buffer overflow. Your version of the function has the same problem as gets() -- it will just scribble all over memory when you enter more characters than can be put into the array. Most (if not all) experienced programmers will not use gets() for that reason.

readstring(char s[], int arraysize) 
{
   fgets(s,arraysize,stdin);
}

You should edit your post to use code tags -- very few people will bother to wade through very much unformatted c code.

sorry guys, im new at this and am just figuring out the formatting...

here is the c code:

#define LIMIT 100
#define NL '\n'
#define NC '\0'
#define BC ' '
 
    replace (char s[], char Old, char New) {
      int i;
      for(i=0; s<i>!=NC; i++) {
         if(s[i] == Old) {
            s[i] = New;
         }
      }
   }
 
    trim(char s[]) {
      int n = length(s);
      int d = 0;
      int i = 0;
      while ((n>0) && (s[n-1]==BC)) {
         s[n-1] = NC;
         n = n - 1;
      }
      while((d < n) && (s[d]==BC)) {
         d = d + 1;
      }
      if(d > 0) {
         while(s[i+d] != NC) {
            s[i] = s[i+d];
            i = i + 1;
         }
         s[i] = NC;
      }
   }
 
    readstring(char s[]) {
      char next;
      int i = 0;
      scanf("%c",&next);
      while(next != NL) {
         s[i] = next;
         i = i + 1;
         scanf("%c",&next);
      }
      s[i] = NC;
   }
 
   int length(char s[]) {
      int i=0;
      while(s[i]!= NC) {
         i = i + 1;
      }
      return i;
   }
 
    int indexOf(char S[], char IT[]) {
      int result = -1;
      int n=length(S);
      int k=length(IT);
      int i, j;
      if(k > 0) {
          i=0;
          while((result < 0) && (i<(n-k))) {
             for(j=0; (j<k)&&(S[i+j]==IT[j]); j++) {
             }
             if(j<k) {
                 i=i+1;
             } else {
                 result=i;
             }
          }
      }
      return result;
    }
 
    void substring(char S[], int start, int len, char Result[]) {
        int i=0;
        if((start >= 0) && ((start+len) <= length(S))) {
            while(i < len) {
               Result[i] = S[start+i];
               i = i + 1;
            }
        }
        Result[i] = NC;
    }
 
    char charAt(char S[], int i) {
       char result = NC;
       if(i < length(S)) {
           result = S[i];
       }
       return result;
    }
 
    printstring(char s[]) {
      int i=0;
      printf("{");
      while(s[i] != NC) {
         printf("%c",s[i]);
         i = i + 1;
      }
      printf("}");
   }
 
    printstringln(char s[]) {
      printstring(s);
      printf("%c",NL);
   }

why is printstring using printf() to print only one character at a time??? Thats an awful wast of processing CPU cycles. You could do it all in one line. First, you know there will be four strings for each line, and each column will start at a constant column number. If you divide 80 by 4 then each column must be 80/4 = 20 characters. So let N be the width of each column, or 20 in this case. What you need to do is print each of the 4 strings in a column of 20 characters, and you can do that like this

Using the first line in your example:

char* c1 = "SENT:";
char *c2 = ".WORD";
char *c3 = "0";
char *c4 = "; Initializes the sentinel as 0...";
int N = 20;
printf("%-*s%-*s%-*s%-*s",N,c1,N,c2,N,c3,N,c4);

The '-' in the format string tells printf() to left-justify the text, the '*' means to get the width of the column from the parameter list, and 's' means it is to print a null-terminated string. Now, you will need to replace N in the code above with whatever the user enters as the column width. If the string is longer than the specifiec column width, printf() will ignore the column width and print the whole string.

>“columns for the label, operand, operands, and comment fields are to be neatly aligned.
And how does your pretty printer handle macro assembly using high level constructs? What about assemblers that discourage the traditional formatting? This isn't as trivial a program as it seems at first.

This article has been dead for over six months. Start a new discussion instead.