#! /usr/bin/gawk -f # Last edited on 2005-01-05 23:18:34 by stolfi BEGIN { usage = ( ARGV[0] " -v junk=JUNKFILE < INFILE > OUTFILE" ); abort = -1; # Reads a ".pov" or ".inc" file. # Removes all camera and light_source commands, # replacing them by a call to the "camlight" macro. # Writes the deleted text to "JUNKFILE" (default "junk.inc") if (junk == "") { junk = "junk.inc"; } cmtstate = 0; # 0 = plain, 1 = inside "/*..*/" brastate = 0; # 0 = plain, 1 = waiting opeing "{". povstate = 0; # 0 = plain, 1 = inside "camera", 2 = "light source" hadcam = 0; # TRUE if any "camera" command was found. reset_camera_params(); # Output standard header: printf "// Last edited on DATE TIME by USER\n"; printf "// Processed by remove-cam-lights\n"; eol = 1; # TRUE if last char written to {stdout} is "\n" } function reset_camera_params() { # Resets the camera parameters {cam_{ctr,loc,dir,sky,rot}}: cam_ctr = "??"; # camera's "look_at" cam_loc = "??"; # camera's "location" cam_sky = "??"; # camera's "cam_sky" cam_dir = "??"; # camera's "direction" cam_rot = "??"; # camera's "rotation" } (abort >= 0) { exit abort; } // { lin = $0; # Line cleanup: gsub(/[\011]/, " ", lin); gsub(/[\015]/, "", lin); # Process line up to but not including the final "\n". # However we write "\n" to {junk} after each "*/", # at the end of each "//" comment, and at the end # of each camera/light specification. while (lin != "") { if (cmtstate == 1) { # inside "/*...*/" comment: if (match(lin, /[*][\/]/)) { # Split {lin} just after the "*/": bef = substr(lin,1,RSTART+RLENGTH-1); lin = substr(lin,RSTART+RLENGTH); # Part before "*/" is junk: printf "%s\n", bef > junk; cmtstate = 0; } else { printf "%s", lin > junk; lin = ""; } } else if (brastate == 1) { # Expecting a "{" after "camera" or "light_source": if (match(lin, /^[ ]+/)) { # Split blanks off, remain in same state: bef = substr(lin,1,RSTART+RLENGTH-1); lin = substr(lin,RSTART+RLENGTH); printf "%s", bef; } else if (match(lin, /^([\/][\/]|[\/][*]|[{])/)) { # Get the matched string {key} and split {lin} at it: key = substr(lin,RSTART,RLENGTH); lin = substr(lin,RSTART+RLENGTH); if (key == "{") { printf "%s", key > junk; brastate = 0; } else if (key == "//") { printf "//%s\n", lin > junk; lin = ""; } else if (key == "/*") { printf "/*" > junk; cmtstate = 1; } else { prog_error("bad key"); } } else { data_error("missing \"{\" after camera or light_source"); } } else if (povstate == 1) { # Inside "camera" command if (match(lin, /([\/][\/]|[\/][*]|[{}]|location|sky|look_at|rotate|direction)/)) { # Get the matched string {key} and split {lin} at it: bef = substr(lin,1,RSTART-1); key = substr(lin,RSTART,RLENGTH); lin = substr(lin,RSTART+RLENGTH); # Part before {key} is always junk: printf "%s", bef > junk; if (key == "location") { printf "%s", key > junk; cam_loc = get_camera_param(); } else if (key == "sky") { printf "%s", key > junk; cam_sky = get_camera_param(); } else if (key == "look_at") { printf "%s", key > junk; cam_ctr = get_camera_param(); } else if (key == "rotate") { printf "%s", key > junk; cam_rot = get_camera_param(); } else if (key == "direction") { printf "%s", key > junk; cam_dir = get_camera_param(); } else if (key == "//") { printf "//%s\n", lin > junk; lin = ""; } else if (key == "/*") { printf "/*" > junk; cmtstate = 1; } else if (key == "}") { printf "}\n" > junk; povstate = 0; } else if (key == "{") { data_error("found \"{\" inside camera spec"); } else { prog_error("bad key"); } } else { printf "%s", lin > junk; lin = ""; } } else if (povstate == 2) { # Inside "light_source" directive if (match(lin, /([\/][\/]|[\/][*]|[{}])/)) { # Get the matched string {key} and split {lin} at it: bef = substr(lin,1,RSTART-1); key = substr(lin,RSTART,RLENGTH); lin = substr(lin,RSTART+RLENGTH); # Part before {key} is always junk: printf "%s", bef > junk; if (key == "//") { printf "//%s\n", lin > junk; lin = ""; } else if (key == "/*") { printf "/*" > junk; cmtstate = 1; } else if (key == "}") { printf "}\n" > junk; povstate = 0; } else if (key == "{") { data_error("found \"{\" inside light source spec"); } else { prog_error("bad key"); } } else { printf "%s", lin > junk; lin = ""; } } else { # Normal state ({povstate == 0, cmtstate == 0}) if (match(lin, /([\/][\/]|[\/][*]|camera|light_source)/)) { # Get the matched string {key} and split {lin} at it: bef = substr(lin,1,RSTART-1); key = substr(lin,RSTART,RLENGTH); lin = substr(lin,RSTART+RLENGTH); # Print part before {key}: printf "%s", bef; # Decide next state if (key == "camera") { povstate = 1; brastate = 1; if (hadcam) { data_warning("multiple cameras"); } hadcam = 1; reset_camera_params(); printf "%s", key > junk; } else if (key == "light_source") { povstate = 2; brastate = 1; printf "%s", key > junk; } else if (key == "//") { printf "//%s\n", lin > junk; lin = ""; } else if (key == "/*") { cmtstate = 1; printf "/*" > junk; } else { prog_error("bad key"); } } else { printf "%s", lin; lin = ""; } } } # Process end-of-line: if ((povstate == 0) && (cmtstate == 0)) { printf "\n"; } else { printf "\n" > junk; } } function get_camera_param( par,tag) { # Extracts from the beginning of {lin} a camera parameter, # up to the next parameter keyword ("up", "right", etc.), comment, # or "}". Returns the parameter as result, writes the parsed # portion of {lin} to {junk}, and leaves the remainder in {lin}. # For now, require parameter to be on the same line as the keyword, # with no intervening comments. if (match(lin, /([\/][\/]|[\/][*]|[{}]|location|cam_sky|look_at|right|up|angle|rotate|direction)/)) { # Get the matched string {tag} and split {lin} at it: par = substr(lin,1,RSTART-1); tag = substr(lin,RSTART,RLENGTH); lin = substr(lin,RSTART); if (tag == "{") { data_error("found \"{\" inside camera spec"); } } else { par = lin; lin = ""; } # The {par} string is junk: printf "%s", par > junk; # Cleanup the {par} string: gsub(/^[ ]+/, "", par); gsub(/[ ]+$/, "", par); gsub(/[ ][ ]+/, " ", par); gsub(/[ ][,]/, ",", par); gsub(/[,][ ]/, ",", par); gsub(/[ ][>]/, ">", par); gsub(/[<][ ]/, "<", par); # Check for missing parameter value: if (par == "") { data_error("missing camera parameter value"); return "??"; } else { return par; } } END { if (abort >= 0) { exit abort; } # Check for proper closing of things: if (cmtstate != 0) { param_error("unterminated \"/*...*/\" comment"); } else if (brastate != 0) { param_error("missing \"{\" after \"camera\" or \"light_source\""); } else if (povstate != 0) { param_error("unterminated camera or light source spec"); } if (hadcam == 0) { param_warning("no camera spec found"); } else { # Cleanup camera parameters, generate standard macro call: # Require {cam_sky} to be Y or Z: if (cam_sky == "??") { param_warning("missing camera \"sky\" parameter"); cam_sky = "y"; } else if (cam_sky !~ /^[yz]$/) { param_warning(("non-standard cam_sky \"" cam_sky "\"")); cam_sky = ( "(" cam_sky ")" ); } # Require {cam_ctr}, protect it: if (cam_ctr == "??") { param_warning("missing camera \"look_at\" parameter"); cam_ctr = "<0,0,0>"; } else if (cam_ctr ~ /^[<][-+ 0.]*[,][-+ 0.]*[,][-+ 0.]*[>]$/) { cam_ctr = "<0,0,0>"; } else if (cam_ctr !~ /^[<][-+ 0-9.]*[,][-+ 0-9.]*[,][-+ 0-9.]*[>]$/) { cam_ctr = ( "(" cam_ctr ")" ); } # Build the camera vector {cam_vec}: if (cam_loc != "??") { # Protect the camera location {cam_loc}: if (cam_loc !~ /^[<][-+ 0-9.]*[,][-+ 0-9.]*[,][-+ 0-9.]*[>]$/) { cam_loc = ( "(" cam_loc ")" ); } # Build the camera vector as {cam_loc - cam_ctr}: if (cam_ctr == "<0,0,0>") { cam_vec = cam_loc; } else { cam_vec = ( cam_loc "-" cam_ctr ); } } else if (cam_dir != "??") { # Take the camera direction as the camera vector: cam_vec = cam_dir; } else { param_warning("missing camera \"location\" and \"direction\" parameter"); cam_vec = "<10,10,10>"; } # Rotate the camera is so specified: if (cam_rot != "??") { cam_vec = ( "vrotate(" cam_vec "," cam_rot ")" ); } # Add standard camera spec: printf "\n"; printf "#include \"camlight.inc\"\n"; printf "camlight(%s,%s,1.00,%s,1.0)\n",cam_ctr,cam_vec,cam_sky; } close(junk); } function arg_error(msg) { printf "** %s\n", msg > "/dev/stderr"; abort = 1; exit abort; } function data_error(msg) { printf "%s:%d: «%s»\n", FILENAME, FNR, $0 > "/dev/stderr"; printf "%s:%d: ** %s\n", FILENAME, FNR, msg > "/dev/stderr"; abort = 1; exit abort; } function data_warning(msg) { printf "%s:%d: «%s»\n", FILENAME, FNR, $0 > "/dev/stderr"; printf "%s:%d: warning: %s\n", FILENAME, FNR, msg > "/dev/stderr"; } function param_error(msg) { printf "%s:%d: ** %s\n", FILENAME, FNR, msg > "/dev/stderr"; abort = 1; exit abort; } function param_warning(msg) { printf "%s:%d: warning: %s\n", FILENAME, FNR, msg > "/dev/stderr"; } function prog_error(msg) { printf "%s:%d: ** program error: %s\n", FILENAME, FNR, msg > "/dev/stderr"; abort = 1; exit abort; }