Make parseini properly handle line continuations.
[matthijs/upstream/backupninja.git] / lib / parseini.in
1 # -*- mode: awk; indent-tabs-mode: nil; -*-
2
3 # parseini --- parses 'ini' style configuration files.
4 #
5 # Usage:
6 #   awk -f parseini S=<section> P=<param> <ini file>
7 #
8 # if section is an empty string, then we use the default section
9 #
10 # example ini file:
11
12 #    fruit = apple
13 #    fruit = pear
14 #    multiline = this is a multiline \
15 #    parameter
16 #
17 #    # this is a comment
18 #    [colors]  
19 #    red = yes
20 #    green = no
21 #    blue = maybe
22 #
23 #    [ocean] 
24 #    fish = red 
25 #    fish = blue
26 #       
27 # example usage:
28 #    > awk -f parseini S=ocean P=fish testfile.ini 
29 # would return: 
30 #    red
31 #    blue
32 #
33    
34 BEGIN { 
35     readlines = 1 
36     implied = 1 
37
38
39 # remove lines starting with #, but not #!
40 /^#[^!]/ {next} 
41
42 # skip blank
43 /^[ \r\t]*$/ {next} 
44
45 # we want to read the lines of the matched section
46 # and disable for other sections
47 /^\[.+\][ \r\t]*$/ { 
48     continueline = 0 
49     if (S && implied) { 
50         nline = 0 
51         implied = 0 
52     } 
53     if (S && match($0, "^\\[" S "\\][ \n]*")) { 
54         # we found the section, so start reading.
55         readlines = 1 
56     } 
57     else { 
58         # no section, so stop reading lines
59         if (readlines) readlines = 0 
60     } 
61     next 
62
63
64 # when reading, store lines.
65
66
67     if (!readlines) next 
68     line[nline++] = $0 
69     if ($0 ~ /\\[ \r\t]*$/) 
70         continueline = 1 
71     else 
72         continueline = 0 
73
74
75 # process the read lines lines, matching parameters
76
77 END { 
78     # if section is set but implied is still true
79     # then we never found the section, so use everything
80     if (S && implied) { 
81         nline = 0 
82     } 
83
84     # if have P then find P in read lines and get values 
85     if (P) { 
86         MATCH = "^[ \r\t]*" P "[ \r\t]*=" 
87         continueline = 0 
88         for (x = 0; x < nline; ++x) { 
89             v = line[x] 
90             if (continueline) { 
91                 sub(/[ \r\t]+$/, "", v) 
92                 if (v ~ /\\$/) { 
93                    v = substr(v, 1, length(v)-1) 
94                    sub(/[ \r\t]+$/, "", v) 
95                 } else {
96                                         continueline = 0
97                                 }
98                 if (v) value[nvalue++] = v 
99             } 
100             else if (v ~ MATCH) { 
101                 sub(MATCH, "", v) 
102                 sub(/^[ \r\t]+/, "", v) 
103                 sub(/[ \r\t]+$/, "", v) 
104                 if (v ~ /\\$/) { 
105                     continueline = 1 
106                     v = substr(v, 1, length(v)-1) 
107                     sub(/[ \r\t]+$/, "", v) 
108                 } 
109                 if (v) value[nvalue++] = v 
110             } 
111         } 
112         # copy parameter definition to output array 
113         nline = nvalue 
114         for (x = 0; x < nvalue; ++x) 
115             line[x] = value[x] 
116     } 
117
118     # trim all leading & trailing whitespace; 
119     # except for leading whitespace in continuation lines, 
120  
121     for (x = 0; x < nline; ++x) { 
122         sub(/^[ \r\t]+/, "", line[x]) 
123         sub(/[ \r\t]+$/, "", line[x]) 
124     } 
125  
126     # output the final result
127     for (x = 0; x < nline; ++x) 
128         print line[x] 
129
130     if (nline) exit 0 
131     else exit 1 
132 }