Mercurial > repo
comparison interps/cfunge/cfunge-src/tools/fprint_funcs.sh @ 996:859f9b4339e6
<Gregor> tar xf egobot.tar.xz
author | HackBot |
---|---|
date | Sun, 09 Dec 2012 19:30:08 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
995:6883f5911eb7 | 996:859f9b4339e6 |
---|---|
1 #!/usr/bin/env bash | |
2 # -*- coding: utf-8 -*- | |
3 ########################################################################### | |
4 # # | |
5 # cfunge - A standard-conforming Befunge93/98/109 interpreter in C. # | |
6 # Copyright (C) 2008-2009 Arvid Norlander # | |
7 # # | |
8 # This program is free software: you can redistribute it and/or modify # | |
9 # it under the terms of the GNU General Public License as published by # | |
10 # the Free Software Foundation, either version 3 of the License, or # | |
11 # (at the proxy's option) any later version. Arvid Norlander is a # | |
12 # proxy who can decide which future versions of the GNU General Public # | |
13 # License can be used. # | |
14 # # | |
15 # This program is distributed in the hope that it will be useful, # | |
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
18 # GNU General Public License for more details. # | |
19 # # | |
20 # You should have received a copy of the GNU General Public License # | |
21 # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
22 # # | |
23 ########################################################################### | |
24 | |
25 # This script contains utility functions for the fingerprint scripts. It is | |
26 # not meant for stand alone use. | |
27 | |
28 # Clean up locale settings to prevent strange bugs: | |
29 unset LANG LC_ALL LC_COLLATE LC_CTYPE LC_NUMERIC | |
30 export LANG=C | |
31 export LC_ALL=C | |
32 | |
33 # Print error message to stderr and exit. Each parameter is printed on it's own | |
34 # line prefixed by "ERROR: ". | |
35 die() { | |
36 local emsg | |
37 for emsg in "$@"; do | |
38 echo "ERROR: $emsg" >&2 | |
39 echo -ne '\a' >&2 | |
40 done | |
41 exit 1 | |
42 } | |
43 | |
44 warn() { | |
45 local emsg | |
46 for emsg in "$@"; do | |
47 echo "WARNING: $emsg" >&2 | |
48 echo -ne '\a' >&2 | |
49 done | |
50 echo -ne '\a' >&2 | |
51 sleep 5 | |
52 } | |
53 | |
54 progress() { | |
55 echo " * ${1}..." | |
56 } | |
57 progresslvl2() { | |
58 echo " * ${1}..." | |
59 } | |
60 | |
61 status() { | |
62 echo " ${1}" | |
63 } | |
64 statuslvl2() { | |
65 echo " ${1}" | |
66 } | |
67 | |
68 # Char to decimal (ASCII value) | |
69 # $1 Name of output variable | |
70 # $2 Char to convert. | |
71 ord() { | |
72 printf -v "$1" '%d' "'$2" | |
73 } | |
74 | |
75 # $1 is fingerprint name | |
76 # Returns if ok, otherwise it dies. | |
77 checkfprint() { | |
78 local FPRINT="$1" | |
79 if [[ $FPRINT =~ ^[A-Z0-9]{4}$ ]]; then | |
80 status "Fingerprint name $FPRINT ok style." | |
81 elif [[ $FPRINT =~ ^[^\ /\\]{4}$ ]]; then | |
82 status "Fingerprint name $FPRINT probably ok (but not common style)." | |
83 status "Make sure each char is in the ASCII range 0-254." | |
84 status "Note that alphanumeric (upper case only) fingerprint names are strongly preferred." | |
85 else | |
86 die "Not valid format for fingerprint name." | |
87 fi | |
88 } | |
89 | |
90 # Parse a spec file. Will make use of FD 4. | |
91 # $1 Fingerprint name. | |
92 # There must be a file named ${1}.spec in the current directory | |
93 # The caller should make sure it exists. The caller should also have | |
94 # called checkfprint to validate it. | |
95 # This will set/change these globals: | |
96 # Strings: | |
97 # fp_URL Fingerprint URL | |
98 # fp_F109_URI URI for Funge-109 | |
99 # fp_CONDITION #if condition for compilation. | |
100 # fp_SAFE Safe for sandbox mode (true/false) | |
101 # fp_OPCODES Defined opcodes. | |
102 # fp_DESCRIPTION Description | |
103 # Arrays: | |
104 # fp_ALIASES An array with aliases for the fingerprint. | |
105 # (text format, not hex) | |
106 # fp_OPCODE_NAMES Opcode names (index: opcode's ASCII value). | |
107 # fp_OPCODE_DESC Opcode descriptions (index: opcode's ASCII value). | |
108 # | |
109 # On return IFS is unset. | |
110 # This function calls die in case of errors. | |
111 parse_spec() { | |
112 local FPRINT="$1" | |
113 # Variables | |
114 fp_URL="" | |
115 fp_F109_URI="NULL" | |
116 fp_CONDITION="" | |
117 fp_SAFE="" | |
118 fp_OPCODES="" | |
119 fp_DESCRIPTION="" | |
120 fp_ALIASES=() | |
121 fp_OPCODE_NAMES=() | |
122 fp_OPCODE_DESC=() | |
123 | |
124 if [[ ! -f "${FPRINT}.spec" ]]; then | |
125 die "${FPRINT}.spec not found (or not a normal file)." | |
126 fi | |
127 | |
128 progresslvl2 "Opening spec file" | |
129 IFS=$'\n' | |
130 local line type data instr name desc number | |
131 # First line is %fingerprint-spec 1.[234] | |
132 # (1.2 is still supported). | |
133 exec 4<"${FPRINT}.spec" || die "Couldn't open spec file for reading on FD 4." | |
134 statuslvl2 "Success." | |
135 progresslvl2 "Parsing spec file" | |
136 read -ru 4 line | |
137 if ! [[ "$line" =~ ^%fingerprint-spec\ 1\.[234]$ ]]; then | |
138 die "Either the spec file is not a fingerprint spec, or it is not a supported version (1.2, 1.3 and 1.4 are currently supported)." | |
139 fi | |
140 | |
141 # 0: pre-"begin instrs" | |
142 # 1: "begin-instrs" | |
143 local parsestate=0 | |
144 | |
145 while read -ru 4 line; do | |
146 if [[ "$line" =~ ^# ]]; then | |
147 continue | |
148 fi | |
149 if [[ $parsestate == 0 ]]; then | |
150 IFS=':' read -rd $'\n' type data <<< "$line" || true | |
151 case $type in | |
152 "%fprint") | |
153 if [[ "$FPRINT" != "$data" ]]; then | |
154 die "%fprint and spec file name doesn't match." | |
155 fi | |
156 ;; | |
157 "%url") | |
158 fp_URL="$data" | |
159 ;; | |
160 "%f108-uri") | |
161 warn "%f108-uri is deprecated. Replace with %f109-uri and update spec format to 1.4." | |
162 fp_F109_URI="\"$data\"" | |
163 ;; | |
164 "%f109-uri") | |
165 fp_F109_URI="\"$data\"" | |
166 ;; | |
167 "%condition") | |
168 fp_CONDITION="$data" | |
169 ;; | |
170 "%alias") | |
171 fp_ALIASES+=( "$data" ) | |
172 ;; | |
173 "%desc") | |
174 fp_DESCRIPTION="$data" | |
175 ;; | |
176 "%safe") | |
177 fp_SAFE="$data" | |
178 ;; | |
179 "%begin-instrs") | |
180 parsestate=1 | |
181 ;; | |
182 "#"*) | |
183 # A comment, ignore | |
184 ;; | |
185 *) | |
186 die "Unknown entry $type found in ${FPRINT}." | |
187 ;; | |
188 esac | |
189 else | |
190 if [[ "$line" == "%end" ]]; then | |
191 break | |
192 fi | |
193 # Parse instruction lines. | |
194 IFS=$' \t' read -rd $'\n' instr name desc <<< "$line" | |
195 | |
196 fp_OPCODES+="$instr" | |
197 ord number "${instr:0:1}" | |
198 fp_OPCODE_NAMES[$number]="$name" | |
199 fp_OPCODE_DESC[$number]="$desc" | |
200 fi | |
201 done | |
202 | |
203 unset IFS | |
204 | |
205 statuslvl2 "Done parsing." | |
206 | |
207 exec 4<&- | |
208 | |
209 progresslvl2 "Validating the parsed data" | |
210 | |
211 if [[ "$fp_URL" ]]; then | |
212 statuslvl2 "%url: Good, not empty" | |
213 else | |
214 die "%url is not given or is empty." | |
215 fi | |
216 | |
217 if [[ "$fp_DESCRIPTION" ]]; then | |
218 statuslvl2 "%desc: Good, not empty" | |
219 else | |
220 die "%desc is not given or is empty." | |
221 fi | |
222 | |
223 if [[ ( "$fp_SAFE" == "true" ) || ( "$fp_SAFE" == "false" ) ]]; then | |
224 statuslvl2 "%safe: OK" | |
225 else | |
226 die "%safe must be either true or false." | |
227 fi | |
228 | |
229 if [[ "$fp_OPCODES" =~ ^[A-Z]+$ ]]; then | |
230 # Check that they are sorted. | |
231 local previousnr=0 | |
232 for (( i = 0; i < ${#fp_OPCODES}; i++ )); do | |
233 ord number "${fp_OPCODES:$i:1}" | |
234 if [[ $previousnr -ge $number ]]; then | |
235 die "Instructions not sorted or there are duplicates" | |
236 else | |
237 previousnr=$number | |
238 fi | |
239 done | |
240 statuslvl2 "Instructions: OK" | |
241 else | |
242 die "The opcodes are not valid. The must be in the range A-Z" | |
243 fi | |
244 return 0 | |
245 } |