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 }