From: WILLS@LSTC2VM.stortek.com (Cheyenne Wills)
Subject: Re: More Than LineAtATime
Organization: StorageTek SW Engineering
Date: Mon, 9 Nov 1992 15:24:23 GMT

With all the talk of processing strings across line boundries and
performing character scanning etc.  I have an example that might
address some of those.
 
The following program was written to strip comments and blank
lines from a C program.  It handles the case where comments (or
blank lines) might occur within quoted strings.
 
Anyway... Enjoy
 
=========================================================================
#
# Removes all C comments and blank lines from a C file.
#
# cmd syntax: infile outfile
#
global outline
global in,out,quotechar,process
 
procedure main(args)
    # Build the input and output fileids
    fidi := args[1]
    fido := args[2]
 
    in := open(fidi,"r") | stop("Unable to open ",fidi," for input")
    out := open(fido,"w") | stop("Unable to open ",fido," for output")
 
    outline := ""                     # Start with an empty line
    process := standard               # And "standard" input processing
 
    while line := trim(read(in)) do { # Read a line from input
        if *line == 0 then next       # Throw away empty lines
        line ||:= "\n"                # Add a newline (for later)
        line ? while not pos(0) do    # Scan the line using current
            process()                 # process
        }
 
    flush()                           # Flush anything we have left
    close(in)                         # close files
    close(out)
end
 
#
# "Standard" string filter.
#
# This procedure looks for quotes, and start of comments.
# When it finds a quoted string, it sets the current process to inquote
# When it finds a comment, it sets the current process to incomment
#
# Moves scanned data to output.
#
procedure standard()
 
    # Write all data upto a quote or start of a comment OR the end
    # of a line.  If writing to the end of a line, return.
    outwrite( tab(upto('"\'/'))) | (outwrite(tab(0)) & return)
 
    # Found either the start of a comment or the start of a quote
    if ="/*" then              # Check for start of a comment.
        process := incomment   # Yep -- process is now in a comment.
    else if any('\'"') then {  # Check for start of a quoted string
        quotechar := move(1)   # Yep -- Get the quote delimiter
        process := inquote     # Set processing for quoted strings
        outwrite(quotechar)    # and dump quote char out.
        }
    else outwrite(move(1))     # False alarm -- just a "/" -- write it.
 
    return                     # And return
end
 
#
# Process a quoted string.  The string delimiter is in quotechar.
# Will set process back to standard when the quotechar is found.
# Handles C escaped characters
#
procedure inquote()
    # Write everything upto either the quote char or backslash
    #   OR write to the end of the line and return.
    outwrite( tab(upto( quotechar ++ '\\')) ) |
        (outwrite(tab(0)) & return)
 
    # If we have an escaped character.. then just dump it and return
    outwrite(="\\") & outwrite(move(1)) & return
 
    outwrite( =quotechar )     # Write the quote char (hopefully)
    process := standard        # set process back to standard.
    return                     # And return.
end
 
#
# Process a comment.  Just throw data away until we find the
# comment end string.  When end of comment is reached, set process
# back to standard.
#
procedure incomment()
 
    tab(upto('*')) |  # Skip upto either an asterisk OR
        (tab(0) & return)  # skip the rest of the line and return.
 
    if ="*/" then process := standard  # reset back to standard on EOC
    else move(1)               # otherwise throw the "*" away
    return                     # And return
end
 
#
# Put data to the output file.  Will not write blank lines.
#
procedure outwrite(data)
   local xout,rest
   outline ||:= data           # Append the data to the current buffer
   xout := ""
   rest := ""
   outline ? {                 # Scan the current buffer
       xout := tab(upto('\n')) & move(1) # Split on newlines
       rest := tab(0)
   }
   xout := trim(xout)          # Trim trailing blanks
   if *xout > 0 then write(out,xout) # If not an empty string then write
   outline := rest             # and set the output buffer to
   return                      # the remaining data and return.
end
 
#
# Flush any remaining data from our output buffer.
#
procedure flush()
   local xout,rest
   xout := ""
   rest := ""
   while *outline > 0 do {     # Keep processing as long as there is
       outline ? {             # data left in the buffer.
           xout := tab(upto('\n')) & move(1)  # Split on newlines
           rest := tab(0)
       }
       xout := trim(xout)      # Trim trailing blanks
       if *xout > 0 then write(out,xout) # If not an empty string then
       outline := rest         # Write it out.  And continue with
       }                       # the rest of the data.
   return                      # Return when all done..
end
=========================================================================
+---------------------------------------+-------------------------------+
| +-----+                               | Cheyenne Wills                |
| |     |       "From here on up it is  | Storage Technology Corporation|
| |  +--+--+      downhill all the way" | 2270 South 88th St.           |
| |  |  |  |                            | Louisville, Co. 80028-4232    |
| +--+--+  |                            |                               |
|    |     |                            | Cheyenne_Wills@stortek.com    |
|    +-----+                            | cheyenne@witsend.stortek.com  |
+---------------------------------------+-------------------------------+
Newsgroups: comp.lang.icon