fork download
  1. # xref.awk - cross reference an awk program
  2.  
  3. BEGIN {
  4.  
  5. # create array of keywords to be ignored by lexer
  6. asplit("BEGIN:END:atan2:break:close:continue:cos:delete:" \
  7. "do:else:exit:exp:for:getline:gsub:if:in:index:int:" \
  8. "length:log:match:next:print:printf:rand:return:sin:" \
  9. "split:sprintf:sqrt:srand:sub:substr:system:while",
  10. keywords,":")
  11.  
  12. # build the symbol-state table
  13. split("00:00:00:00:00:00:00:00:00:00:" \
  14. "20:10:10:12:12:11:07:00:00:00:" \
  15. "08:08:08:08:08:33:08:00:00:00:" \
  16. "08:44:08:36:08:08:08:00:00:00:" \
  17. "08:44:45:42:42:41:08",machine,":")
  18.  
  19. # parse the input and store an intermediate representation
  20. # of the cross-reference information
  21.  
  22. # set up the machine
  23. state = 1
  24.  
  25. # run the machine
  26. for (;;) {
  27.  
  28. # get next symbol
  29. symb = lex()
  30. nextstate = substr(machine[state symb],1,1)
  31. act = substr(machine[state symb],2,1)
  32.  
  33. # perform required action
  34. if ( act == "0" )
  35. ; # do nothing
  36. else if ( act == "1" ) {
  37. if ( ! inarray(tok,names) )
  38. names[++nnames] = tok
  39. lines[tok,++xnames[tok]] = NR }
  40. else if ( act == "2" ) {
  41. if ( tok in local ) {
  42. tok = tok "(" funcname ")"
  43. if ( ! inarray(tok,names) )
  44. names[++nnames] = tok
  45. lines[tok,++xnames[tok]] = NR }
  46. else {
  47. tok = tok "()"
  48. if ( ! inarray(tok,names) )
  49. names[++nnames] = tok
  50. lines[tok,++xnames[tok]] = NR } }
  51. else if ( act == "3" ) {
  52. funcname = tok
  53. flines[tok] = NR }
  54. else if ( act == "4" )
  55. braces++
  56. else if ( act == "5" ) {
  57. braces--
  58. if ( braces == 0 ) {
  59. for ( temp in local )
  60. delete local[temp]
  61. funcname = ""
  62. nextstate = 1 } }
  63. else if ( act == "6" ) {
  64. local[tok] = 1 }
  65. else if ( act == "7" )
  66. break
  67. else if ( act == "8" ) {
  68. print "error: xref.awk: line " NR ": aborting" \
  69. > "/dev/con"
  70. exit 1 }
  71.  
  72. # finished with current token
  73. state = nextstate }
  74.  
  75. # finished parsing, now ready to print output
  76. for ( i = 1; i <= nnames; i++ ) {
  77. printf "%d ", xnames[names[i]] |"sort +1"
  78. if ( index(names[i],"(") == 0 )
  79. printf "%s(%d)", names[i], flines[names[i]] |"sort +1"
  80. else
  81. printf "%s", names[i] |"sort +1"
  82. for ( j = 1; j <= xnames[names[i]]; j++ )
  83. if ( lines[names[i],j] != lines[names[i],j-1] )
  84. printf " %d", lines[names[i],j] |"sort +1"
  85. printf "\n" |"sort +1" }
  86.  
  87. } # END OF PROGRAM
  88.  
  89. function asplit(str,arr,fs, n) { n = split(str,temp_asplit,fs)
  90. for ( i = 1; i <= n; i++ ) arr[temp_asplit[i]]++ }
  91.  
  92. function inarray(val,arr, j) {
  93. for ( j in arr )
  94. if ( arr[j] == val ) return j
  95. return "" }
  96.  
  97. function lex() {
  98.  
  99. for (;;) {
  100.  
  101. if ( tok == "(eof)" ) return 7
  102.  
  103. while ( length(line) == 0 )
  104. if ( getline line == 0 ) {
  105. tok = "(eof)"; return 7 }
  106.  
  107. sub(/^[ \t]+/,"",line) # remove white space,
  108. sub(/^"([^"]|\\")*"/,"",line) # quoted strings,
  109. sub(/^\/([^\/]|\\\/)+\//,"",line) # regular expressions,
  110. sub(/^#.*/,"",line) # and comments
  111.  
  112. if ( line ~ /^function/ ) {
  113. tok = "function"; line = substr(line,9); return 1 }
  114. else if ( line ~ /^{/ ) {
  115. tok = "{"; line = substr(line,2); return 2 }
  116. else if ( line ~ /^}/ ) {
  117. tok = "}"; line = substr(line,2); return 3 }
  118. else if ( match(line,/^[A-Za-z_][A-Za-z_0-9]*\[/) ) {
  119. tok = substr(line,1,RLENGTH-1)
  120. line = substr(line,RLENGTH+1)
  121. return 5 }
  122. else if ( match(line,/^[A-Za-z_][A-Za-z_0-9]*\(/) ) {
  123. tok = substr(line,1,RLENGTH-1)
  124. line = substr(line,RLENGTH+1)
  125. if ( ! ( tok in keywords ) ) return 6 }
  126. else if ( match(line,/^[A-Za-z_][A-Za-z_0-9]*/) ) {
  127. tok = substr(line,1,RLENGTH)
  128. line = substr(line,RLENGTH+1)
  129. if ( ! ( tok in keywords ) ) return 4 }
  130. else {
  131. match(line,/^[^A-Za-z_{}]/)
  132. tok = substr(line,1,RLENGTH)
  133. line = substr(line,RLENGTH+1) } } }
  134.  
Success #stdin #stdout 0.01s 4636KB
stdin
        # xref.awk - cross reference an awk program

        BEGIN {

                # create array of keywords to be ignored by lexer
                asplit("BEGIN:END:atan2:break:close:continue:cos:delete:" \
                        "do:else:exit:exp:for:getline:gsub:if:in:index:int:"  \
                        "length:log:match:next:print:printf:rand:return:sin:" \
                        "split:sprintf:sqrt:srand:sub:substr:system:while",
                        keywords,":")

                # build the symbol-state table
                split("00:00:00:00:00:00:00:00:00:00:" \
                          "20:10:10:12:12:11:07:00:00:00:" \
                          "08:08:08:08:08:33:08:00:00:00:" \
                          "08:44:08:36:08:08:08:00:00:00:" \
                          "08:44:45:42:42:41:08",machine,":")

                # parse the input and store an intermediate representation
                # of the cross-reference information

                # set up the machine
                state = 1

                # run the machine
                for (;;) {

                        # get next symbol
                        symb = lex()
                        nextstate = substr(machine[state symb],1,1)
                        act = substr(machine[state symb],2,1)

                        # perform required action
                        if ( act == "0" )
                                ; # do nothing
                        else if ( act == "1" ) {
                                if ( ! inarray(tok,names) )
                                        names[++nnames] = tok
                                lines[tok,++xnames[tok]] = NR }
                        else if ( act == "2" ) {
                                if ( tok in local ) {
                                        tok = tok "(" funcname ")"
                                        if ( ! inarray(tok,names) )
                                                names[++nnames] = tok
                                        lines[tok,++xnames[tok]] = NR }
                                else {
                                        tok = tok "()"
                                        if ( ! inarray(tok,names) )
                                                names[++nnames] = tok
                                        lines[tok,++xnames[tok]] = NR } }
                        else if ( act == "3" ) {
                                funcname = tok
                                flines[tok] = NR }
                        else if ( act == "4" )
                                braces++
                        else if ( act == "5" ) {
                                braces--
                                if ( braces == 0 ) {
                                        for ( temp in local )
                                                delete local[temp]
                                        funcname = ""
                                        nextstate = 1 } }
                        else if ( act == "6" ) {
                                local[tok] = 1 }
                        else if ( act == "7" )
                                break
                        else if ( act == "8" ) {
                                print "error: xref.awk: line " NR ": aborting" \
                                        > "/dev/con"
                                exit 1 }

                        # finished with current token
                        state = nextstate }

                # finished parsing, now ready to print output
                for ( i = 1; i <= nnames; i++ ) {
                        printf "%d ", xnames[names[i]] |"sort +1"
                        if ( index(names[i],"(") == 0 )
                                printf "%s(%d)", names[i], flines[names[i]] |"sort +1"
                        else
                                printf "%s", names[i] |"sort +1"
                        for ( j = 1; j <= xnames[names[i]]; j++ )
                                if ( lines[names[i],j] != lines[names[i],j-1] )
                                        printf " %d", lines[names[i],j] |"sort +1"
                        printf "\n" |"sort +1" }

                } # END OF PROGRAM

        function asplit(str,arr,fs,  n) { n = split(str,temp_asplit,fs)
                for ( i = 1; i <= n; i++ ) arr[temp_asplit[i]]++ }

        function inarray(val,arr,  j) {
            for ( j in arr )
                if ( arr[j] == val ) return j
            return "" }

        function lex() {

                for (;;) {

                        if ( tok == "(eof)" ) return 7

                        while ( length(line) == 0 )
                                if ( getline line == 0 ) {
                                        tok = "(eof)"; return 7 }

                        sub(/^[ \t]+/,"",line)                                # remove white space,
                        sub(/^"([^"]|\\")*"/,"",line)                # quoted strings,
                        sub(/^\/([^\/]|\\\/)+\//,"",line)        # regular expressions,
                        sub(/^#.*/,"",line)                                        # and comments

                        if ( line ~ /^function/ ) {
                                tok = "function"; line = substr(line,9); return 1 }
                        else if ( line ~ /^{/ ) {
                                tok = "{"; line = substr(line,2); return 2 }
                        else if ( line ~ /^}/ ) {
                                tok = "}"; line = substr(line,2); return 3 }
                        else if ( match(line,/^[A-Za-z_][A-Za-z_0-9]*\[/) ) {
                                tok = substr(line,1,RLENGTH-1)
                                line = substr(line,RLENGTH+1)
                                return 5 }
                        else if ( match(line,/^[A-Za-z_][A-Za-z_0-9]*\(/) ) {
                                tok = substr(line,1,RLENGTH-1)
                                line = substr(line,RLENGTH+1)
                                if ( ! ( tok in keywords ) ) return 6 }
                        else if ( match(line,/^[A-Za-z_][A-Za-z_0-9]*/) ) {
                                tok = substr(line,1,RLENGTH)
                                line = substr(line,RLENGTH+1)
                                if ( ! ( tok in keywords ) ) return 4 }
                        else {
                                match(line,/^[^A-Za-z_{}]/)
                                tok = substr(line,1,RLENGTH)
                                line = substr(line,RLENGTH+1) } } }
stdout
10 act() 31 34 36 40 51 54 56 63 65 67
1 arr(asplit) 90
2 arr(inarray) 93 94
1 asplit(89) 6
3 braces() 55 57 58
2 flines() 53 79
1 fs(asplit) 89
3 funcname() 42 52 61
16 i() 76 77 78 79 81 82 83 84 90
3 inarray(92) 37 43 48
6 j() 82 83 84
3 j(inarray) 93 94
3 keywords() 10 125 129
1 lex(97) 29
31 line() 103 104 107 108 109 110 112 113 114 115 116 117 118 119 120 122 123 124 126 127 128 131 132 133
6 lines() 39 45 50 83 84
4 local() 41 59 60 64
3 machine() 17 30 31
15 names() 37 38 43 44 48 49 77 78 79 81 82 83 84
2 n(asplit) 89 90
3 nextstate() 30 62 73
4 nnames() 38 44 49 76
5 NR() 39 45 50 53 68
8 RLENGTH() 119 120 123 124 127 128 132 133
4 state() 23 30 31 73
1 str(asplit) 89
3 symb() 29 30 31
2 temp() 59 60
2 temp_asplit() 89 90
31 tok() 37 38 39 41 42 43 44 45 47 48 49 50 52 53 64 101 105 113 115 117 119 123 125 127 129 132
1 val(inarray) 94
5 xnames() 39 45 50 77 82