Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/awk -f
- BEGIN {
- nkeys[depth = 0] = keynum = 0
- building_array = building_hash = building_string = 0
- if (!(valid_chars = ENVIRON["VALID_VARNAME_CHARS"])) {
- for (c = 48; c < 58; c++)
- valid_chars = valid_chars sprintf("%c", c)
- for (c = 65; c < 91; c++)
- valid_chars = valid_chars sprintf("%c", c)
- for (c = 97; c < 123; c++)
- valid_chars = valid_chars sprintf("%c", c)
- }
- if (filter_object) filter_object = "^" filter_object "$"
- if (filter_value) filter_value = "^" filter_value "$"
- }
- ############################################### FUNCTIONS
- function dprint(msg) { if (debug) print ": DEBUG1", msg }
- function dprint2(msg) { if (debug >= 2) print ": DEBUG2", msg }
- function dprint3(msg) { if (debug >= 3) print ": DEBUG3", msg }
- function lprint(line) { print (local ? "local " : "") line }
- function trim_match()
- {
- match_text = substr($0, RSTART, RLENGTH)
- $0 = substr($0, RSTART + RLENGTH)
- return match_text
- }
- function trim_keyword()
- {
- keylen = length(keynum > 0 ? keynum : key[depth,nkeys[depth]])
- keynum = 0
- if (!keylen) return
- x = keyword
- keyword = substr(keyword, 0, length(keyword) - keylen - 1)
- # NB: The "-1" is for keyword separator "_"
- dprint2(sprintf("TRIM KEY ([%s] => [%s])", x, keyword))
- }
- function objsafe(name)
- {
- gsub(("[^" valid_chars "]"), "_", name)
- return name
- }
- function json_print(object, value)
- {
- if (object !~ filter_object) return
- if (value !~ filter_value) return
- gsub(/'/, "&\\\\&&", value)
- object = objsafe(object)
- lprint(object "='" value "'")
- }
- function json_print_type(object, type)
- {
- if (!keyword) return
- if (object !~ filter_object) return
- if (type)
- lprint(object "_type=" type)
- else if (building_array)
- lprint(object "_type=array")
- else if (building_hash)
- lprint(object "_type=hash")
- else
- lprint(object "_type=scalar")
- }
- function json_print_keys(object, depth)
- {
- keys = ""
- for (k = 1; k <= nkeys[depth]; k++) {
- if (printed[key[depth,k]]) continue
- printed[key[depth,k]] = 1
- keys = keys " " key[depth,k]
- }
- json_print(object, substr(keys, 2))
- }
- function json_unset_value(object)
- {
- lprint(objsafe(object) "_value=")
- }
- function json_filtered_unset_value(object)
- {
- if (object !~ filter_object) return
- return json_unset_value(object)
- }
- function json_objname()
- {
- objname = ""
- if (building_array) {
- objname = keyword "_" building_array++
- dprint3(sprintf("RETURN ARRAY OBJNAME [%s]", objname))
- } else if (building_hash) {
- objname = keyword "_" building_hash++
- dprint3(sprintf("RETURN HASH OBJNAME [%s]", objname))
- } else if (building_string) {
- objname = keyword
- dprint3(sprintf("RETURN STRING OBJNAME [%s]", objname))
- } else if (depth <= 1 && keyword) {
- objname = keyword
- dprint3(sprintf("RETURN ROOT OBJNAME [%s]", objname))
- }
- if (objname) return objname
- # NB: If non-NULL current-depth key, increment for separator
- if ((keylen = length(key[depth,nkeys[depth]]))) keylen++
- objname = substr(keyword, 0, length(keyword) - keylen) "_" nkeys[depth]
- dprint3(sprintf("RETURN OBJNAME [%s]", objname))
- return objname
- }
- ############################################### MAIN LOOP
- { while ($0) { # Loop until done processing everything on this line
- if (building_string) {
- while (match($0, /^[^"]*\\"/)) value = value trim_match()
- if (!match($0, /^[^"]*"/)) { # No ending quote
- value = value $0
- next # Continue reading on next line
- }
- objname = json_objname()
- building_string = 0
- value = value substr($0, RSTART, RLENGTH - 1)
- trim_match()
- sub(/^[[:space:]]*,[[:space:]]*/, "")
- json_print(objname, value)
- json_print_type(objname)
- trim_keyword()
- if (depth <= 1) json_print_type(keyword "_" nk)
- }
- ################################### OPENING PATTERNS
- else if (match($0, /^[[:space:]]*{[[:space:]]*/)) {
- building_hash = (depth > 0)
- if (depth > 1) {
- x = keyword
- nk = nkeys[depth]
- keyword = keyword "_" nk
- keynum = nk
- dprint2(sprintf("APPEND HASH ([%s] => [%s])",
- x, keyword))
- }
- nkeys[++depth] = 0
- trim_match()
- } else if (keyword && match($0, /^[[:space:]]*\[/)) {
- building_array = 1
- trim_match()
- }
- ################################### OBJECTS
- else if (match($0, /^[[:space:]]*"[^"]+"[[:space:]]*:[[:space:]]*/)) {
- nkeys[depth]++
- nk = nkeys[depth]
- key[depth,nk] = trim_match()
- sub(/^[[:space:]]*"/, "", key[depth,nk])
- sub(/"[[:space:]]*:[[:space:]]*$/, "", key[depth,nk])
- kp = key[depth,nk]
- dprint(sprintf("START OBJECT key[%u,%u]=\"%s\"",
- depth, nk, kp))
- if (keyword && !building_hash)
- json_print(keyword "_" nk, objsafe(kp))
- if (!building_hash) {
- x = keyword
- keyword = keyword (keyword ? "_" : "") kp
- dprint2(sprintf("APPEND KEY ([%s] => [%s])",
- x, keyword))
- }
- }
- ################################### PROPERTIES
- else if (keyword && match($0, /^[[:space:]]*"/)) {
- value = ""
- trim_match()
- while (match($0, /^[^"]*\\"/)) value = value trim_match()
- if (!match($0, /^[^"]*"/)) {
- building_string = 1
- value = $0
- next
- }
- value = value substr($0, RSTART, RLENGTH - 1)
- trim_match()
- sub(/^[[:space:]]*,[[:space:]]*/, "")
- object = json_objname()
- nk = nkeys[depth]
- if (depth <= 1) {
- json_print(object, value)
- if (!building_array) json_print_type(object)
- } else {
- json_print(object, key[depth,nk])
- json_print(object "_value", value)
- }
- if (building_hash) {
- if (!value) json_filtered_unset_value(object)
- } else if (!building_array) {
- trim_keyword()
- json_print_type(keyword "_" nk)
- }
- }
- else if (keyword && match($0, \
- /^[[:space:]]*[^[:space:],}\]]+[[:space:]]*/ \
- )) {
- value = trim_match()
- sub(/^[[:space:]]*/, "", value)
- sub(/[[:space:]]*$/, "", value)
- sub(/^[[:space:]]*,[[:space:]]*/, "")
- json_print(keyword, value)
- json_print_type(keyword)
- trim_keyword()
- if (!building_array) json_print_type(keyword "_" nkeys[depth])
- }
- ################################### CLOSING PATTERNS
- else if (match($0, /^[[:space:]]*\][[:space:]]*/)) {
- json_print(keyword "_len", --building_array)
- json_print_type(keyword, "array")
- nk = nkeys[depth]
- items = building_array
- building_array = 0
- trim_keyword()
- trim_match()
- sub(/^[[:space:]]*,[[:space:]]*/, "")
- json_print_type(keyword "_" nk, "array")
- dprint(sprintf("END ARRAY key[%u,%u]=\"%s\"" \
- " holding %u object%s", depth, nk,
- key[depth,nk], items, items != 1 ? "s" : ""))
- }
- else if (match($0, /^[[:space:]]*}[[:space:]]*/)) {
- nk = nkeys[depth]
- if (keyword && depth >= 1) {
- hashname = key[depth-1,nkeys[depth-1]]
- json_print(keyword, hashname)
- json_print(keyword "_len", nk)
- json_print_type(keyword, "hash")
- }
- building_hash = 0
- depth-- # NB: Done prior to calling trim_keyword()
- trim_keyword()
- trim_match()
- sub(/^[[:space:]]*,[[:space:]]*/, "")
- building_hash = (depth > 1)
- if (depth == 1) {
- objname = keyword "_" nkeys[depth]
- json_print_type(objname, "hash")
- }
- if (depth < 0) {
- json_print_keys(keyword, depth+1)
- dprint(sprintf("END HASH key[%u,%u]=\"%s\"" \
- " holding %u object%s", depth+2,
- nkeys[depth+2],
- key[depth+2,nkeys[depth+2]],
- nkeys[depth+3],
- nkeys[depth+3] != 1 ? "s" : ""))
- } else if (kp = key[depth,nkeys[depth]]) {
- dprint(sprintf("END HASH key[%u,%u]=\"%s\"" \
- " holding %u object%s", depth,
- nkeys[depth], kp, nkeys[depth+1],
- nkeys[depth+1] != 1 ? "s" : ""))
- }
- }
- } }
- ############################################### END
- END {
- json_print_keys(keyword "_keys", 1)
- dprint(sprintf("END HASH holding %u object%s", nkeys[1],
- nkeys[1] != 1 ? "s" : ""))
- }
Add Comment
Please, Sign In to add comment