1# mkstrtable.awk 2# Copyright (C) 2003, 2004, 2008 g10 Code GmbH 3# 4# This program is free software; you can redistribute it and/or 5# modify it under the terms of the GNU General Public License as 6# published by the Free Software Foundation; either version 2 of 7# the License, or (at your option) any later version. 8# 9# This program is distributed in the hope that it will be useful, 10# but WITHOUT ANY WARRANTY; without even the implied warranty of 11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12# General Public License for more details. 13# 14# You should have received a copy of the GNU General Public License 15# along with this program; if not, write to the Free Software 16# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 17# 18# As a special exception, g10 Code GmbH gives unlimited permission to 19# copy, distribute and modify the C source files that are the output 20# of mkstrtable.awk. You need not follow the terms of the GNU General 21# Public License when using or distributing such scripts, even though 22# portions of the text of mkstrtable.awk appear in them. The GNU 23# General Public License (GPL) does govern all other use of the material 24# that constitutes the mkstrtable.awk program. 25# 26# Certain portions of the mkstrtable.awk source text are designed to be 27# copied (in certain cases, depending on the input) into the output of 28# mkstrtable.awk. We call these the "data" portions. The rest of the 29# mkstrtable.awk source text consists of comments plus executable code 30# that decides which of the data portions to output in any given case. 31# We call these comments and executable code the "non-data" portions. 32# mkstrtable.h never copies any of the non-data portions into its output. 33# 34# This special exception to the GPL applies to versions of mkstrtable.awk 35# released by g10 Code GmbH. When you make and distribute a modified version 36# of mkstrtable.awk, you may extend this special exception to the GPL to 37# apply to your modified version as well, *unless* your modified version 38# has the potential to copy into its output some of the text that was the 39# non-data portion of the version that you started with. (In other words, 40# unless your change moves or copies text from the non-data portions to the 41# data portions.) If your modification has such potential, you must delete 42# any notice of this special exception to the GPL from your modified version. 43 44# This script outputs a source file that does define the following 45# symbols: 46# 47# static const char msgstr[]; 48# A string containing all messages in the list. 49# 50# static const int msgidx[]; 51# A list of index numbers, one for each message, that points to the 52# beginning of the string in msgstr. 53# 54# msgidxof (code); 55# A macro that maps code numbers to idx numbers. If a DEFAULT MESSAGE 56# is provided (see below), its index will be returned for unknown codes. 57# Otherwise -1 is returned for codes that do not appear in the list. 58# You can lookup the message with code CODE with: 59# msgstr + msgidx[msgidxof (code)]. 60# 61# The input file has the following format: 62# CODE1 ... MESSAGE1 (code nr, <tab>, something, <tab>, msg) 63# CODE2 ... MESSAGE2 (code nr, <tab>, something, <tab>, msg) 64# ... 65# CODEn ... MESSAGEn (code nr, <tab>, something, <tab>, msg) 66# ... DEFAULT-MESSAGE (<tab>, something, <tab>, fall-back msg) 67# 68# Comments (starting with # and ending at the end of the line) are removed, 69# as is trailing whitespace. The last line is optional; if no DEFAULT 70# MESSAGE is given, msgidxof will return the number -1 for unknown 71# index numbers. 72# 73# The field to be used is specified with the variable "textidx" on 74# the command line. It defaults to 2. 75# 76# The variable nogettext can be set to 1 to suppress gettext markers. 77# 78# The variable prefix can be used to prepend a string to each message. 79# 80# The variable namespace can be used to prepend a string to each 81# variable and macro name. 82 83BEGIN { 84 FS = "[\t]+"; 85# cpos holds the current position in the message string. 86 cpos = 0; 87# msg holds the number of messages. 88 msg = 0; 89 print "/* Output of mkstrtable.awk. DO NOT EDIT. */"; 90 print ""; 91 header = 1; 92 if (textidx == 0) 93 textidx = 2; 94# nogettext can be set to 1 to suppress gettext noop markers. 95} 96 97/^#/ { next; } 98 99header { 100 if ($1 ~ /^[0123456789]+$/) 101 { 102 print "/* The purpose of this complex string table is to produce"; 103 print " optimal code with a minimum of relocations. */"; 104 print ""; 105 print "static const char " namespace "msgstr[] = "; 106 header = 0; 107 } 108 else 109 print; 110} 111 112!header { 113 sub (/\#.+/, ""); 114 sub (/[ ]+$/, ""); # Strip trailing space and tab characters. 115 116 if (/^$/) 117 next; 118 119# Print the string msgstr line by line. We delay output by one line to be able 120# to treat the last line differently (see END). 121 if (last_msgstr) 122 { 123 if (nogettext) 124 print " \"" last_msgstr "\" \"\\0\""; 125 else 126 print " gettext_noop (\"" last_msgstr "\") \"\\0\""; 127 } 128 last_msgstr = prefix $textidx; 129 130# Remember the error code and msgidx of each error message. 131 code[msg] = $1; 132 pos[msg] = cpos; 133 cpos += length (last_msgstr) + 1; 134 msg++; 135 136 if ($1 == "") 137 { 138 has_default = 1; 139 exit; 140 } 141} 142END { 143 if (has_default) 144 coded_msgs = msg - 1; 145 else 146 coded_msgs = msg; 147 148 if (nogettext) 149 print " \"" last_msgstr "\";"; 150 else 151 print " gettext_noop (\"" last_msgstr "\");"; 152 print ""; 153 print "static const int " namespace "msgidx[] ="; 154 print " {"; 155 for (i = 0; i < coded_msgs; i++) 156 print " " pos[i] ","; 157 print " " pos[coded_msgs]; 158 print " };"; 159 print ""; 160 print "static inline int"; 161 print namespace "msgidxof (int code)"; 162 print "{"; 163 print " return (0 ? 0"; 164 165# Gather the ranges. 166 skip = code[0]; 167 start = code[0]; 168 stop = code[0]; 169 for (i = 1; i < coded_msgs; i++) 170 { 171 if (code[i] == stop + 1) 172 stop++; 173 else 174 { 175 print " : ((code >= " start ") && (code <= " stop ")) ? (code - " \ 176 skip ")"; 177 skip += code[i] - stop - 1; 178 start = code[i]; 179 stop = code[i]; 180 } 181 } 182 print " : ((code >= " start ") && (code <= " stop ")) ? (code - " \ 183 skip ")"; 184 if (has_default) 185 print " : " stop + 1 " - " skip ");"; 186 else 187 print " : -1);"; 188 print "}"; 189} 190