/[webpac]/trunk/openisis/lfmt.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/openisis/lfmt.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 239 - (show annotations)
Mon Mar 8 17:49:13 2004 UTC (20 years ago) by dpavlin
File MIME type: text/plain
File size: 35628 byte(s)
including openisis 0.9.0 into webpac tree

1 /*
2 openisis - an open implementation of the CDS/ISIS database
3 Version 0.8.x (patchlevel see file Version)
4 Copyright (C) 2001-2003 by Erik Grziwotz, erik@openisis.org
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 see README for more information
21 EOH */
22
23 /*
24 $Id: lfmt.c,v 1.14 2003/04/08 00:20:52 kripke Exp $
25 implementation of record cooking.
26 */
27
28 #include <string.h> /* memset et al */
29
30 #include "ldb.h"
31
32
33 #define LFMT_DBG LOG_WARN /* level of debugging */
34
35 /* ************************************************************
36 private types
37 */
38 typedef struct { /* function definition */
39 const char *name; /* hmmm ... fixed char[] probably faster */
40 const char *sign;
41 int tag;
42 } LfmtToken;
43
44 typedef enum {
45 LFMT_MP, /* proof */
46 LFMT_MH, /* heading */
47 LFMT_MD /* data */
48 } lfmtMode;
49
50 typedef struct LfmtIter_ { /* value iterator */
51 const unsigned char *def; /* position in format where iter was opened. */
52 const unsigned char *end; /* position in format where iter was closed. */
53 int pos; /* next field pos */
54 int off; /* offset to start search for next subfield */
55 int occ; /* next occ */
56 /* filter */
57 int tag;
58 char sub;
59 char submode; /* primary loop (counted by occ) is over subfields. */
60 int from; /* primary range. */
61 int to;
62 int sfrom; /* additional subfield range. */
63 int sto;
64 } LfmtIter;
65
66 #define LFMT_NITER 8
67
68 typedef struct LfmtRec_ { /* record context -- pushed by the r in REF */
69 struct LfmtRec_ *prev;
70 Rec *r;
71 int frame; /* stack frame associated with this record */
72 const unsigned char *loop; /* position in format where loop was opened. */
73 LfmtIter iter[LFMT_NITER]; /* iterators in loop */
74 int occ; /* loop occ */
75 unsigned char i; /* iterator count */
76 char more; /* more flag */
77 char had; /* had flag */
78 char sub; /* database's subfield separator, typically ^ or $ */
79 } LfmtRec;
80
81 typedef struct LfmtFmt_ { /* format context -- pushed by @ */
82 struct LfmtFmt_ *prev;
83 const unsigned char *f;
84 const unsigned char *e; /* end -- just for paranoia check */
85 lfmtMode mode;
86 int upcase; /* uppercase flag */
87 } LfmtFmt;
88
89
90 typedef struct { /* other type */
91 const LfmtToken *tok; /* recognized token */
92 int data; /* start of params in output */
93 int used; /* used len of output up to our params */
94 char pos; /* position in signature */
95 char want; /* currently expected type */
96 char expl; /* explicit flag */
97 char rec; /* record flag */
98 } LfmtFrame;
99
100
101 /*
102 list of special token tags after the format tags 1 .. 999.
103 unlike formatting tokens, which just emit a field with their negative tag,
104 the literal's tag is reset to 0,
105 and all other tokens emit fields with tags based on their parameters.
106
107 tokens are organized in groups of (up to) 16.
108 the group of an operator determines it's precedence.
109 */
110 #define LFMT_DEFGROUP(i) ((i) << 4) /* * 16 */
111 #define LFMT_GROUP(i) ((i) >> 4)
112
113 /* token groups */
114 enum {
115 LFMT_LITERAL = 63, /* literals group starting from 63*16 = 1008 */
116 /* syntactical groups starting from 64*16 = 0x400 */
117 LFMT_FUNCTIONS,
118 LFMT_VALUES = 96, /* starting from 96*16 = 0x600 */
119 LFMT_ITERATORS,
120 LFMT_OPITER, /* iterator operators */
121 LFMT_OPSTR, /* string operators */
122 LFMT_OPMUL, /* multiplicative operators */
123 LFMT_OPADD, /* additive operators */
124 LFMT_OPREL, /* relational operators */
125 LFMT_OPBOOL, /* boolean operators */
126 LFMT_OPASSIGN, /* assignment */
127 LFMT_STOPPER = 128, /* starting from 128*16 = 0x800 */
128 LFMT_SYNTAX
129 };
130
131 enum {
132 /* literals */
133 LFMT_LIT = LFMT_DEFGROUP( LFMT_LITERAL ),
134 LFMT_COND,
135 LFMT_REP,
136 LFMT_COMM,
137 LFMT_BARE, /* field of bareword C&A literal */
138 LFMT_NUMBER, /* standalone numeric literal */
139 /* functions */
140 LFMT_OPEN = LFMT_DEFGROUP( LFMT_FUNCTIONS ),
141 LFMT_AMP,
142 LFMT_AT,
143 LFMT_XREF,
144 LFMT_S,
145 LFMT_Z,
146 LFMT_F,
147 /* */
148 LFMT_MDL,
149 LFMT_MDU,
150 LFMT_MHL,
151 LFMT_MHU,
152 LFMT_MPL,
153 LFMT_MPU,
154 /* values */
155 LFMT_SI = LFMT_DEFGROUP( LFMT_VALUES ),
156 LFMT_EI,
157 /* iterators */
158 LFMT_V = LFMT_DEFGROUP( LFMT_ITERATORS ),
159 LFMT_D,
160 LFMT_N,
161 /* operator groups by decreasing precedence */
162 LFMT_INDEX = LFMT_DEFGROUP( LFMT_OPITER ),
163 LFMT_SUBFIELD,
164 LFMT_STAR = LFMT_DEFGROUP( LFMT_OPSTR ),
165 LFMT_DOT, LFMT_INDENT,
166 LFMT_MUL = LFMT_DEFGROUP( LFMT_OPMUL ),
167 LFMT_DIV,
168 LFMT_PLUS = LFMT_DEFGROUP( LFMT_OPADD ),
169 LFMT_MINUS,
170 LFMT_EQ = LFMT_DEFGROUP( LFMT_OPREL ),
171 LFMT_NE, LFMT_LT, LFMT_LE, LFMT_GT, LFMT_GE, LFMT_CT,
172 LFMT_AND = LFMT_DEFGROUP( LFMT_OPBOOL ),
173 LFMT_OR, LFMT_NOT,
174 LFMT_ASSIGN = LFMT_DEFGROUP( LFMT_OPASSIGN ),
175 /* stoppers */
176 LFMT_COMMA = LFMT_DEFGROUP( LFMT_STOPPER ),
177 LFMT_RANGE,
178 LFMT_CLOSE,
179 /* syntax */
180 LFMT_BLANK = LFMT_DEFGROUP( LFMT_SYNTAX ),
181 LFMT_LOOP,
182 LFMT_WHILE,
183 LFMT_REF,
184 LFMT_IF, LFMT_THEN, LFMT_ELSE, LFMT_FI,
185 LFMT_SELECT, LFMT_CASE, LFMT_ELSECASE, LFMT_ENDSEL,
186 LFMT__LAST
187 };
188
189 /*
190 while fields emitted by formatting and literal tokens
191 have tags between -1 and -1023 (0xffffffff to 0xfffffc01)
192 with all high bits set, numerics have lowest negative values
193 ranging from 0x80000000 to 0xbfffffff (-2147483648 to -1073741825).
194 That means the highest two bits are 1 and 0.
195 All numeric fields have a val of NULL and use len to hold a number.
196 Besides pure int or fixed-point numbers,
197 there are other numerical types:
198 next two bits may indicate a range or field selector.
199 The lower 3 bytes may give fractional part or range end.
200 */
201 #define LFMT_NMASK 0xf0000000L /* highest bits 1 and 0 mark a number */
202 #define LFMT_NUM 0x80000000L /* basic number */
203 #define LFMT_ITR 0xa0000000L /* with iterator bit */
204 #define LFMT_VAL 0x00ffffffL /* mask for 3 bytes additional info */
205 /* is any numeric */
206 #define LFMT_ISNUM(t) (LFMT_NUM == (LFMT_NMASK & (t)))
207 /* is pure int */
208 #define LFMT_ISINT(t) (LFMT_NUM == (t))
209 /* is iterator */
210 #define LFMT_ISITR(t) (LFMT_ITR == (LFMT_NMASK & (t)))
211
212 /* ************************************************************
213 private data
214 */
215 static const LfmtToken number = { "", "_1i", LFMT_NUMBER };
216 /* while a numeric *field* has large LFMT_NUM tag,
217 the anonymous number *token* has a literal tag,
218 so we don't take it as high precedence operator.
219 */
220 static const LfmtToken blank = { "_", "_0o_", LFMT_BLANK };
221 static const LfmtToken loop = { "loop", "_0o_", LFMT_LOOP };
222
223 /*
224 32 = 33 = ! 34 = " 35 = # 36 = $ 37 = % 38 = & 39 = '
225 40 = ( 41 = ) 42 = * 43 = + 44 = , 45 = - 46 = . 47 = /
226 48 = 0 49 = 1 50 = 2 51 = 3 52 = 4 53 = 5 54 = 6 55 = 7
227 56 = 8 57 = 9 58 = : 59 = ; 60 = < 61 = = 62 = > 63 = ?
228 64 = @ 65 = A 66 = B 67 = C 68 = D 69 = E 70 = F 71 = G
229 72 = H 73 = I 74 = J 75 = K 76 = L 77 = M 78 = N 79 = O
230 80 = P 81 = Q 82 = R 83 = S 84 = T 85 = U 86 = V 87 = W
231 88 = X 89 = Y 90 = Z 91 = [ 92 = \ 93 = ] 94 = ^ 95 = _
232 96 = ` 97 = a 98 = b 99 = c 100 = d 101 = e 102 = f 103 = g
233 104 = h 105 = i 106 = j 107 = k 108 = l 109 = m 110 = n 111 = o
234 112 = p 113 = q 114 = r 115 = s 116 = t 117 = u 118 = v 119 = w
235 120 = x 121 = y 122 = z 123 = { 124 = | 125 = } 126 = ~
236 */
237 /* stops dictionary search */
238 static const char sentinel[] = "\x7f";
239 #define ENDDICT { sentinel, NULL, 0 }
240
241 static const LfmtToken dictSpecial[] = {
242 { "", "_0", 0 }, /* eof */
243 { "!", "_1x", OPENISIS_FMT_ESC },
244 { "\"", "_1x", LFMT_COND },
245 { "#", "_0", OPENISIS_FMT_SHARP },
246 /* { "$", "_0", LFMT_LIT }, */
247 { "%", "_0", OPENISIS_FMT_PERCENT },
248 { "&", "_1as_", LFMT_AMP },
249 { "'", "_1x", LFMT_LIT },
250 { "(", "_0", LFMT_OPEN },
251 { ")", "_0", LFMT_CLOSE },
252 { "*", "n1n", LFMT_MUL },
253 { "+", "n1n", LFMT_PLUS },
254 { ",", "_0", LFMT_COMMA },
255 { "-", "n1n", LFMT_MINUS },
256 { ".", "s1i", LFMT_DOT },
257 { "..","_0", LFMT_RANGE },
258 { "/", "n1n", LFMT_DIV }, /* alias { "/", "_0", OPENISIS_FMT_SLASH }, */
259 { "/*","_1x", LFMT_COMM },
260 /* 0 - 9 */
261 { ":", "s1s", LFMT_CT },
262 { ":=","v1f", LFMT_ASSIGN },
263 /* { ";", "b_", LFMT_LIT }, */
264 { "<", "n1n", LFMT_LT },
265 { "<=","n1n", LFMT_LE },
266 { "<>","n1n", LFMT_NE },
267 { "=", "n1n", LFMT_EQ },
268 { ">", "n1n", LFMT_GT },
269 { ">=","n1n", LFMT_GE },
270 /* { "?", "b_", LFMT_LIT }, */
271 { "@", "_1a", LFMT_AT },
272 /* A - Z */
273 { "[", "v1nn", LFMT_INDEX },
274 /* { "\\", "_0", LFMT_LIT }, */
275 { "]", "_0", LFMT_CLOSE },
276 { "^", "v1c", LFMT_SUBFIELD },
277 /* { "_", "_0", LFMT_LIT }, */
278 /* { "`", "_0", LFMT_LIT }, */
279 /* a - z */
280 { "{", "_0", OPENISIS_FMT_OPEN },
281 { "|", "_1x", LFMT_REP },
282 { "}", "_0", OPENISIS_FMT_CLOSE },
283 { "~", "_1n", LFMT_NOT },
284 ENDDICT };
285 static const LfmtToken dictA[] = { ENDDICT };
286 static const LfmtToken dictB[] = {
287 { "B", "_0", OPENISIS_FMT_B },
288 ENDDICT };
289 static const LfmtToken dictC[] = {
290 { "C", "_1i", OPENISIS_FMT_C },
291 ENDDICT };
292 static const LfmtToken dictD[] = {
293 { "D", "_1i", LFMT_D },
294 ENDDICT };
295 static const LfmtToken dictE[] = {
296 { "E", "_1i", LFMT_EI },
297 { "ELSE", "_1s_", LFMT_ELSE },
298 ENDDICT };
299 static const LfmtToken dictF[] = {
300 /* { "F", "_1nii", LFMT_F }, */
301 { "F", "_1i", OPENISIS_FMT_F },
302 ENDDICT };
303 static const LfmtToken dictG[] = { ENDDICT };
304 static const LfmtToken dictH[] = { ENDDICT };
305 static const LfmtToken dictI[] = {
306 { "I", "_0", OPENISIS_FMT_I },
307 { "IF", "_1n", LFMT_IF },
308 ENDDICT };
309 static const LfmtToken dictJ[] = { ENDDICT };
310 static const LfmtToken dictK[] = { ENDDICT };
311 static const LfmtToken dictL[] = {
312 { "LINK", "_1s_", OPENISIS_FMT_LINK },
313 ENDDICT };
314 static const LfmtToken dictM[] = {
315 { "M", "_1ii", OPENISIS_FMT_M },
316 { "MDL", "_0", LFMT_MDL },
317 { "MDU", "_0", LFMT_MDU },
318 { "MHL", "_0", LFMT_MHL },
319 { "MHU", "_0", LFMT_MHU },
320 { "MPL", "_0", LFMT_MPL },
321 { "MPU", "_0", LFMT_MPU },
322 ENDDICT };
323 static const LfmtToken dictN[] = {
324 { "N", "_1i", LFMT_N },
325 { "NC", "_0i", OPENISIS_FMT_NC },
326 ENDDICT };
327 static const LfmtToken dictO[] = { ENDDICT };
328 static const LfmtToken dictP[] = {
329 { "PICT", "_1s", OPENISIS_FMT_PICT },
330 ENDDICT };
331 static const LfmtToken dictQ[] = {
332 { "QC", "_0", OPENISIS_FMT_QC },
333 ENDDICT };
334 static const LfmtToken dictR[] = {
335 { "REF", "_2rs_", LFMT_REF },
336 ENDDICT };
337 static const LfmtToken dictS[] = {
338 { "S", "_1s_", LFMT_S },
339 ENDDICT };
340 static const LfmtToken dictT[] = {
341 { "TAB", "_0i", OPENISIS_FMT_TAB },
342 ENDDICT };
343 static const LfmtToken dictU[] = {
344 { "UL", "_0", OPENISIS_FMT_UL },
345 ENDDICT };
346 static const LfmtToken dictV[] = {
347 { "V", "_1i", LFMT_V },
348 ENDDICT };
349 static const LfmtToken dictW[] = { ENDDICT };
350 static const LfmtToken dictX[] = {
351 { "X", "_0i", OPENISIS_FMT_X },
352 ENDDICT };
353 static const LfmtToken dictY[] = { ENDDICT };
354 static const LfmtToken dictZ[] = {
355 { "Z", "_1is", LFMT_Z },
356 ENDDICT };
357
358 static const LfmtToken * const dictAZ[26] = {
359 dictA, dictB, dictC, dictD, dictE, dictF, dictG, dictH, dictI,
360 dictJ, dictK, dictL, dictM, dictN, dictO, dictP, dictQ, dictR,
361 dictS, dictT, dictU, dictV, dictW, dictX, dictY, dictZ
362 };
363
364
365 /* character conversion */
366 static const unsigned char upcase[256] = {
367 0,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
368 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
369 ' ','!','"','#','$','%','&','\'', '(',')','*','+',',','-','.','/',
370 '0','1','2','3','4','5','6','7', '8','9',':',';','<','=','>','?',
371 '@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
372 'P','Q','R','S','T','U','V','W','X','Y','Z','[','\\',']','^','_',
373 '`','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
374 'P','Q','R','S','T','U','V','W','X','Y','Z','{','|','}','~',' ',
375 '?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?',
376 '?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?',
377 '?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?',
378 '?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?',
379 '?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?',
380 '?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?',
381 '?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?',
382 '?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?'
383 };
384
385 enum {
386 DIG=0x01, /* digit */
387 ALP=0x02, /* ascii alphabetic */
388 IDE=0x04, /* other identifier character */
389 LIT=0x10, /* as signature type, eat literal (a,c,i,x) */
390 ALT=ALP|LIT
391 };
392 /* character type */
393 static const unsigned char ctype[256] = {
394 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
395 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
396 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
397 DIG,DIG,DIG,DIG,DIG,DIG,DIG,DIG,DIG,DIG, 0, 0, 0, 0, 0, 0,
398 /*'@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',*/
399 0,ALP,ALP,ALP,ALP,ALP,ALP,ALP,ALP,ALP,ALP,ALP,ALP,ALP,ALP,ALP,
400 /*'P','Q','R','S','T','U','V','W','X','Y','Z','[','\\',']','^','_',*/
401 ALP,ALP,ALP,ALP,ALP,ALP,ALP,ALP,ALP,ALP,ALP, 0, 0, 0, 0,IDE,
402 0,ALT,ALP,ALT,ALP,ALP,ALP,ALP,ALP,ALT,ALP,ALP,ALP,ALP,ALP,ALP,
403 ALP,ALP,ALP,ALP,ALP,ALP,ALP,ALP,ALT,ALP,ALP, 0, 0, 0, 0, 0,
404 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
405 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
406 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
407 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
408 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
409 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
410 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
411 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
412 };
413
414
415 /* ************************************************************
416 private functions
417 */
418 /* don't rely on braindead ctype.h, it may use locale */
419 #define ISALPHA(u) ( ALP & ctype[(unsigned char)(u)])
420 #define ISDIGIT(u) ( DIG & ctype[(unsigned char)(u)])
421 #define ISALNUM(u) ((ALP|DIG) & ctype[(unsigned char)(u)])
422 #define ISIDENT(u) ((ALP|DIG|IDE) & ctype[(unsigned char)(u)])
423 #define ISLITER(u) ( LIT & ctype[(unsigned char)(u)])
424
425 /* ************************************************************
426 package functions
427 */
428 /* ************************************************************
429 public functions
430 */
431
432 Rec* rFmt ( Rec *buf, const char *fmt, Rec *irec )
433 {
434 /* context */
435 Rec *o = buf;
436 #define ADD( ntag, s, n ) do { \
437 RADD( o, ntag, s, n, o!=buf ); \
438 if ( NULL == o ) goto outofmem; \
439 } while(0)
440 #define CAT( s, n ) do { \
441 RCAT( o, s, n, o!=buf ); \
442 if ( NULL == o ) goto outofmem; \
443 } while(0)
444 /* field add */
445 #define FADD( f ) ADD( f.tag, f.val, f.len )
446 /* string add */
447 #define SADD( ntag, s ) ADD( ntag, s, strlen(s) )
448 #define SCAT( s ) CAT( s, strlen(s) )
449 #define SERR( err ) do { \
450 o = rMsg( o, o!=buf, -LOG_ERROR, \
451 "@%d: %s", fp - f->f, err ); \
452 if ( NULL == o ) goto outofmem; \
453 } while(0)
454 #define SERR1( fmt, a ) do { \
455 o = rMsg( o, o!=buf, -LOG_ERROR, \
456 "@%d: " fmt, fp - f->f, a ); \
457 if ( NULL == o ) goto outofmem; \
458 } while(0)
459 #define SERR2( fmt, a, b ) do { \
460 o = rMsg( o, o!=buf, -LOG_ERROR, \
461 "@%d: " fmt, fp - f->f, a, b ); \
462 if ( NULL == o ) goto outofmem; \
463 } while(0)
464 /* number add */
465 #define NADD( i, d ) do { \
466 ADD( LFMT_NUM | (d), NULL, 0 ); \
467 o->field[o->len - 1].val = NULL; \
468 o->field[o->len - 1].len = i; \
469 } while(0)
470
471 LfmtFrame stack[128], *s = stack; /* current frame (always == stack+sp) */
472 int sp = -1;
473 /* push new frame for token t */
474 #define PUSHFRAME( t ) do { \
475 if ( ++sp == sizeof(stack)/sizeof(stack[0]) ) goto overflow; \
476 s = stack+sp; \
477 memset( s, 0, sizeof(*s) ); \
478 s->data = o->len; \
479 s->used = o->used; \
480 s->tok = (t); \
481 s->want = (t)->sign[2]; \
482 } while(0)
483
484 LfmtFmt fmt0, *f = NULL; /* default and current format */
485 const unsigned char *fp = NULL; /* format pointer */
486 #define PUSHFORMAT( pfmt, fstr ) do { \
487 memset( pfmt, 0, sizeof(*(pfmt)) ); \
488 (pfmt)->prev = f; \
489 f = (pfmt); \
490 fp = f->f = (const unsigned char *)fstr; \
491 f->e = fp + strlen(fstr); \
492 } while(0)
493
494 LfmtRec rec0, *r = NULL; /* default and current record */
495 #define PUSHRECORD( prec, nrec ) do { \
496 memset( prec, 0, sizeof(*(prec)) ); \
497 (prec)->prev = r; \
498 r = (prec); \
499 r->frame = sp; \
500 r->r = nrec; \
501 r->sub = '^'; \
502 } while(0)
503
504 int tlen = 0; /* token length */
505
506
507 PUSHFRAME( &blank );
508 s->rec = 1;
509 PUSHFORMAT( &fmt0, fmt );
510 PUSHRECORD( &rec0, irec );
511
512 o->dbid = irec->dbid ;
513 o->rowid = irec->rowid;
514
515
516 for ( ;; fp += tlen ) {
517 const LfmtToken *tok = NULL;
518 Field lit;
519 unsigned char u;
520 int start = s->data + s->pos; /* start of current param in output */
521 int flds = o->len - start; /* # fields for current param */
522 int vpos = 0; /* pos in dict where we had match of tlen chars */
523 int dpos = 0; /* pos in dict */
524 int expl = 0;
525 unsigned char eatlit = 0;
526 const LfmtToken *dict;
527 enum {
528 CLOSE_OP, /* don't close anything, operator wants field */
529 CLOSE_VAR, /* close variables only */
530 CLOSE_FIELD, /* coerce field only */
531 CLOSE_PARAM, /* compact param only (eat comma) */
532 CLOSE_EXPL, /* close frame explicitly (eat closing token) */
533 CLOSE_IMPL /* close frame implicitly, continue on token */
534 } close;
535 static const char *closename[] = {
536 "", "var", "field", "param", "expl", "impl" };
537
538 lit.tag = 0;
539 tlen = 0; /* verified length */
540
541 /*
542 LOG_DBG( LFMT_DBG,
543 "frame %s%c%s id %d pos %d got %d want %c%s",
544 s->tok->name, s->expl ? '(' : ' ', s->tok->sign, s->tok->tag,
545 s->pos, o->len - s->data, s->want, flds ? " (have)" : "" );
546 */
547 /* lookup token */
548
549 while ( ' ' == (u = upcase[*fp]) ) /* eat whitespace */
550 fp++;
551
552 if ( ISALPHA(u) ) {
553 dict = dictAZ[u-'A'];
554 if ( sentinel != dict->name )
555 u = upcase[ fp[tlen = 1] ];
556 } else if ( ISDIGIT( *fp ) ) {
557 tok = &number; /* read numeric literal */
558 goto countnumber;
559 } else
560 dict = dictSpecial;
561
562 /* tok is the last candidate that matched up to IT'S length */
563 for ( ;; dpos++ ) {
564 unsigned char test;
565 LOG_DBG( LOG_TRACE, "trying token '%s'", dict[dpos].name );
566 if ( tlen && vpos != dpos
567 && strncmp( dict[dpos].name, dict[vpos].name, tlen ) )
568 break; /* ran out of verified length */
569 if ( u == dict[dpos].name[tlen] )
570 vpos = dpos;
571 while ( (test = dict[dpos].name[tlen]) && u == test )
572 /* test this entry -- same pos, next char */
573 u = upcase[ fp[++tlen] ];
574 if ( !test ) /* dict entry ends here -- a hit so far */
575 tok = &dict[dpos];
576 /*
577 LOG_DBG( LFMT_DBG, "\thit on token %s(%s) len %d",
578 tok->name, tok->sign, tlen );
579 */
580 if ( u < test || !u ) /* too large - bail out*/
581 break;
582 }
583
584 if ( NULL != tok ) { /* had some match */
585 if ( tok < &dict[vpos] ) /* had later == longer match */
586 tok = NULL;
587 else if ( dict != dictSpecial ) {
588 /* alpha-token must not be followed by alpha */
589 assert( tlen == (int)strlen(tok->name) );
590 if ( ISALPHA( u ) && ISALPHA( tok->name[tlen-1] ) )
591 tok = NULL;
592 }
593 }
594
595 if ( NULL == tok /* no hit in alphadict */
596 || (dictSpecial == tok && *fp) /* false eof hit in special dict */
597 ) {
598 SERR2( "unrecognized token '%.*s'", tlen+1, fp );
599 goto broken;
600 }
601
602 if ( ISLITER( tok->sign[2] ) ) /* eat literals */
603 switch ( tok->sign[2] ) { /* c, a, i, x */
604 case 'c':
605 if ( (lit.len = (eatlit = fp[tlen]) ? 1 : 0 ) ) {
606 lit.tag = -LFMT_BARE;
607 lit.val = (char *)fp + tlen;
608 tlen++;
609 }
610 break;
611 case 'a':
612 if ( (eatlit = ISIDENT( fp[tlen] )) ) {
613 lit.tag = -LFMT_BARE;
614 lit.val = (char *)fp + tlen;
615 lit.len = 0;
616 while ( ISIDENT( fp[tlen] ) ) {
617 lit.len++;
618 tlen++;
619 }
620 }
621 break;
622 case 'i':
623 countnumber:
624 lit.val = NULL;
625 lit.len = 0;
626 if ( (eatlit = ISDIGIT( u = fp[tlen] )) ) {
627 lit.tag = LFMT_NUM;
628 while ( u && 10 > (u -= '0') ) {
629 lit.len = 10*lit.len + u;
630 u = fp[++tlen];
631 }
632 }
633 /* decimal digits on standalone numeric literal */
634 if ( &number == tok
635 && (unsigned char)('.'-'0') == u
636 && '.' != fp[tlen+1] /* avoid eating 1..2 */
637 ) {
638 int dec = 0;
639 int v = 0;
640 while ( (u = fp[++tlen]) && 10 > (u -= '0') )
641 if ( 6 > dec ) {
642 v = 10*v + u;
643 dec++;
644 }
645 while ( 6 < dec++ ) v *= 10;
646 lit.tag = LFMT_NUM | (v & LFMT_VAL);
647 }
648 break;
649 case 'x':
650 switch ( tok->tag ) {
651 case LFMT_COMM:
652 eatlit='*';
653 break;
654 case OPENISIS_FMT_ESC:
655 eatlit=fp[tlen++];
656 break;
657 default:
658 eatlit=tok->name[0];
659 break;
660 }
661 lit.tag = - tok->tag;
662 lit.val = (char *)fp+1;
663 while ( (u = fp[tlen++])
664 && (eatlit != u || (LFMT_COMM==tok->tag && '/' != fp[tlen]))
665 ) ;
666 if ( !u ) {
667 SERR1( "unterminated %s-literal", tok->name );
668 goto broken;
669 }
670 lit.len = tlen - 2;
671 if ( LFMT_COMM == tok->tag ) {
672 tlen++;
673 continue;
674 }
675 }
676
677 if ( tok->sign[2] ) { /* token wants params */
678 if ( (!eatlit || tok->sign[3]) && (expl = '(' == fp[tlen]) )
679 tlen++; /* eat ( */
680 }
681
682 /* got token */
683 LOG_DBG( LFMT_DBG,
684 "at %d: '%.*s' %s(%s) id %d (%x) group %d pos %d%c of %s%c%s",
685 fp - f->f, tlen > 10 ? 10 : tlen, fp,
686 tok->name, tok->sign, tok->tag, tok->tag, LFMT_GROUP(tok->tag),
687 s->pos, s->want, s->tok->name, s->expl?'(':' ', s->tok->sign
688 );
689
690 /* close what needs to be closed */
691 do {
692 int group = LFMT_GROUP( tok->tag );
693 int dflt, wantnum, gotnum;
694
695 close = CLOSE_FIELD;
696
697 if ( '_' != tok->sign[0] /* token is operator ... */
698 && (s->expl /* ... within explicit frame or ... */
699 || group < LFMT_GROUP( s->tok->tag )) /* ... of higher prec */
700 ) /* we take it -- even as a variable ? */
701 close = 'v' == tok->sign[0] ? CLOSE_OP : CLOSE_VAR;
702 else switch ( tok->tag ) {
703 case LFMT_COMMA:
704 case LFMT_RANGE:
705 close = CLOSE_PARAM;
706 break;
707 case LFMT_CLOSE:
708 close = CLOSE_EXPL;
709 break;
710 }
711
712 if ( CLOSE_VAR > close ) /* leave variable to operator */
713 break; /* close loop */
714
715 if ( flds && LFMT_ISITR( o->field[ o->len-1 ].tag ) ) {
716 /* dereference iterator variable */
717 LfmtIter * iter = r->iter + r->i;
718 if ( ! iter->occ ) {
719 if ( ! iter->from )
720 iter->from = 1; /* field defaults to 1..0 (all) */
721 if ( ! iter->sfrom )
722 iter->sfrom = iter->sto = 1; /* subfield defaults to 1..1 (1st) */
723 }
724
725 LOG_DBG( LFMT_DBG, "iterator %d/%d V%d[%d..%d]^%c[%d..%d]%s",
726 o->field[ o->len-1 ].len, r->occ,
727 iter->tag, iter->from, iter->to,
728 iter->sub ? iter->sub : ' ', iter->sfrom, iter->sto,
729 iter->submode ? " subfield mode" : ""
730 );
731
732 o->len--; /* kill the variable. */
733 /* move to next legal position.
734 In standard mode, where we advance one field occurence at a time,
735 this is just the occ >= from.
736 A legal position may still emit no field,
737 if a selected subfield is not available in the current field occ.
738 In subfield mode, we may have to advance 0, 1 or several field
739 occurences to find next occ of subfield.
740 */
741 r->had = 0;
742 do {
743 int socc;
744 if ( 0 > iter->occ ) /* we were already done */
745 break;
746 /* if have legal occurence, ADD it */
747 if ( iter->occ >= iter->from ) for ( socc=1;; socc++ ) {
748 /* not initialization pass. */
749 Field *v = r->r->field + iter->pos;
750 const char *src = v->val;
751 int len = v->len;
752 if ( iter->sub ) { /* find subfield */
753 const char *p = src + iter->off, *e = src+len;
754 while ( p < e && (
755 r->sub != *p++
756 || e == p
757 || (iter->sub != *p++ && iter->sub != '*')
758 ) )
759 ;
760 iter->off = p - src;
761 if ( p >= e )
762 break;
763 if ( iter->sfrom && socc < iter->sfrom )
764 continue;
765 if ( iter->sto && socc > iter->sto )
766 break;
767 src = p;
768 while ( p < e && r->sub != *p )
769 p++;
770 iter->off += len = p - src;
771 }
772 /* make sure there's enough room, +3 for DATA mode */
773 ADD( v->tag, NULL, len+3 );
774 if ( ! f->mode )
775 CAT( src, len );
776 else {
777 const char *e = src + len;
778 char *dst = (char *)o->field[ o->len - 1 ].val;
779 for ( ; src < e; ) {
780 if ( '<' == *src ) {
781 for ( src++; src < e; *dst++ = *src++ )
782 if ( '=' == *src || '>' == *src ) {
783 while ( '>' != *src++ && src < e )
784 ;
785 if ( src < e && '<' == *src ) { /* have >< */
786 *dst++ = ';';
787 *dst++ = ' ';
788 }
789 break;
790 }
791 } else if ( r->sub == *src ) {
792 if ( ++src == e )
793 break;
794 if ( dst == o->field[ o->len - 1 ].val )
795 ; /* no spearator */
796 else if ( 'a' == *src )
797 *dst++ = ';';
798 else if ( 'j' > *src )
799 *dst++ = ',';
800 else
801 *dst++ = '.';
802 src++;
803 } else
804 *dst++ = *src++;
805 }
806 o->used +=
807 o->field[ o->len - 1 ].len =
808 dst - o->field[ o->len - 1 ].val;
809 if ( LFMT_MD == f->mode )
810 CAT( ". ", 3 );
811 } /* f->mode */
812 if ( f->upcase ) {
813 char *p = (char *)o->field[ o->len - 1 ].val;
814 char *e = p + o->field[ o->len - 1 ].len;
815 for ( ; p < e; p++ )
816 *p = upcase[(unsigned char)*p];
817 }
818 r->had = 1;
819 if ( iter->submode || ! iter->sub )
820 break;
821 }
822 if ( iter->submode ) {
823 if ( iter->occ && iter->occ < iter->from ) /* was skipped */
824 iter->off++;
825 for ( ; iter->pos < r->r->len; iter->pos++, iter->off = 0 )
826 if ( iter->tag == r->r->field[ iter->pos ].tag || ! iter->tag ) {
827 Field *v = r->r->field + iter->pos;
828 const char *p = v->val + iter->off, *e = v->val + v->len;
829 while ( p < e && (
830 r->sub != *p++
831 || e == p
832 || (iter->sub != *p++ && iter->sub != '*')
833 ) )
834 ;
835 if ( p < e ) { /* hit */
836 iter->off = (p - v->val) - 2;
837 break;
838 }
839 }
840 } else {
841 if ( iter->occ )
842 iter->pos++;
843 while ( iter->pos < r->r->len
844 && iter->tag
845 && iter->tag != r->r->field[ iter->pos ].tag
846 )
847 iter->pos++;
848 iter->off = 0;
849 }
850 iter->occ++;
851 if ( iter->pos >= r->r->len /* end of record */
852 || (iter->to && iter->to < iter->occ) /* end of selected occ */
853 ) {
854 iter->occ = -1;
855 break;
856 }
857 } while ( iter->occ <= iter->from );
858
859 if ( 0 < iter->occ ) /* we have a next occurence */
860 r->more = 1;
861 if ( ! r->had && flds && -LFMT_REP == o->field[ o->len - 1 ].tag ) {
862 flds--;
863 o->len--;
864 o->used -= o->field[o->len].len;
865 }
866 r->i++; /* advance to next iterator */
867 } /* dereference iterator variable */
868
869 if ( CLOSE_FIELD > close ) /* leave field to operator */
870 break; /* close loop */
871
872 if ( ! flds ) { /* had no field */
873 if ( CLOSE_PARAM > close ) /* nothing to do */
874 break; /* close loop */
875 } else if ( ! s->expl /* frame is implicit ... */
876 && ( LFMT_LOOP != s->tok->tag /* ... and not a loop ... */
877 || CLOSE_EXPL == close /* ... or we saw a hard closer ... */
878 || (r->i && CLOSE_PARAM == close)
879 /* ... or a loop after 1st iterator on param closer */
880 )
881 ) /** upgrade the closing mode to IMPL */
882 close = CLOSE_IMPL;
883
884 /* close the field, i.e. coerce it */
885 dflt = !flds /* param was not given ... */
886 && (s->pos /* but was started explicitly by a comma like F( 3, ) */
887 || CLOSE_PARAM == close /* or is closed explicitly like F( ,3 ) */
888 );
889 wantnum = 'i' == s->want || 'n' == s->want;
890 gotnum = flds && LFMT_ISNUM( o->field[ o->len-1 ].tag );
891
892 LOG_DBG( LFMT_DBG,
893 "\tclose %s %d%c pos %d%c of %s%c%s id %x",
894 closename[close],
895 flds, flds ? gotnum ? 'n' : 's' : dflt ? 'd' : '-', s->pos, s->want,
896 s->tok->name, s->expl?'(':' ', s->tok->sign, s->tok->tag );
897
898 /* close and fix last field */
899 if ( gotnum && !wantnum ) {
900 /* coerce number to string, so it may get concatenated */
901 char b[32];
902 int ll = lprint( b, o->field[ o->len-1 ].len );
903 b[ll++] = ' ';
904 o->len--;
905 ADD( 0, b, ll );
906 gotnum = 0;
907 }
908
909 if ( CLOSE_PARAM > close )
910 break; /* close loop */
911
912 /* close and fix param */
913 if ( wantnum ) {
914 if ( dflt ) { /* default 0 */
915 NADD( 0, 0 );
916 flds = 1;
917 } else if ( 1 < flds ) {
918 SERR( "multiple fields for numerical param" );
919 goto broken;
920 } else if ( flds && !gotnum ) {
921 SERR( "expected number" );
922 goto broken;
923 }
924 if ( 'i' == s->want ) /* kill decimal */
925 o->field[s->data].tag &= ~LFMT_VAL;
926 } else {
927 if ( dflt ) {
928 SADD( 0, "" );
929 flds = 1;
930 } else if ( gotnum ) {
931 SERR( "expected string" ); /* shouldn't happen !? */
932 goto broken;
933 } else if ( 1 < flds /* concat strings ... */
934 && ! s->rec /* ... unless in record mode frame (blank,loop,ref) */
935 ) {
936 int i;
937 for ( i = start+1; i < o->len; i++ )
938 if ( o->field[i].val )
939 o->field[ start ].len += o->field[ i ].len;
940 o->len = start + 1;
941 }
942 }
943
944 /* done fixing param */
945
946 if ( CLOSE_IMPL > close ) {
947 tok = NULL; /* eat token */
948 if ( CLOSE_EXPL > close ) { /* i.e. CLOSE_PARAM */
949 if ( flds ) { /* increment param pos, set next wanted type */
950 int sl = strlen( s->tok->sign ); /* frame takes sl-2 params */
951 if ( ++(s->pos) < sl-2 ) {
952 if ( '_' != s->tok->sign[ 2 + s->pos ] ) /* repeated param */
953 s->want = s->tok->sign[ 2 + s->pos ]; /* else keep last val */
954 } else if ( '_' != s->tok->sign[sl-1] ) { /* too much */
955 SERR2( "expected at most %d params for '%s'",
956 sl-2, s->tok->name );
957 goto broken;
958 }
959 }
960 break; /* close loop */
961 }
962 }
963
964 /* done with token -- close and fix frame */
965
966 #define KILLARGS() do { \
967 o->len = s->data; \
968 o->used = s->used; \
969 } while(0)
970
971 #define KILLOP() do { \
972 o->len = s->data - 1; \
973 o->used = s->used - (o->field[o->len].val ? o->field[o->len].len : 0); \
974 } while(0)
975
976 switch ( s->tok->tag ) {
977 case LFMT_PLUS: /* arithmetic */
978 case LFMT_MINUS:
979 case LFMT_MUL:
980 case LFMT_DIV: {
981 lll a = o->field[s->data-1].len;
982 lll b = o->field[s->data].len;
983 /* LOG_DBG( LFMT_DBG, "\tarith on %Ld %Ld", a, b ); */
984 switch ( s->tok->tag ) {
985 case LFMT_PLUS: a += b; break;
986 case LFMT_MINUS: a -= b; break;
987 case LFMT_MUL: a *= b; break;
988 case LFMT_DIV: if ( 0 != b ) a /= b; break;
989 }
990 KILLOP();
991 NADD( (int)a, 0 );
992 } break;
993 case LFMT_F: {
994 char b[32];
995 int ll = lprint( b, o->field[ s->data ].len );
996 KILLARGS();
997 ADD( 0, b, ll );
998 } break;
999 case LFMT_V:
1000 r->iter[ r->i ].tag = o->field[ s->data ].len;
1001 /* set iterator field */
1002 o->field[ s->data ].tag = LFMT_ITR | r->iter[ r->i ].tag;
1003 o->field[ s->data ].len = r->i;
1004 break;
1005 case LFMT_INDEX: {
1006 LfmtIter * iter = r->iter + r->i;
1007 if ( 1 != r->occ ) {
1008 SERR( "OOPS! index not within loop" );
1009 goto internalerr;
1010 }
1011 if ( ! iter->sub || (iter->submode = !iter->from) ) {
1012 /* primary loop */
1013 if ( !(iter->from = (int) o->field[ s->data ].len) )
1014 iter->from = 1;
1015 iter->to = s->pos ? (int) o->field[ s->data+1 ].len : iter->from;
1016 } else {
1017 /* additional subfield loop */
1018 if ( !(iter->sfrom = (int) o->field[ s->data ].len) )
1019 iter->sfrom = 1;
1020 iter->sto = s->pos ? (int) o->field[ s->data+1 ].len : iter->sfrom;
1021 }
1022 iter->end = fp + tlen;
1023 KILLARGS();
1024 } break; /* case LFMT_INDEX: */
1025 case LFMT_SUBFIELD:
1026 if ( 1 != r->occ ) {
1027 SERR( "OOPS! subfield not within loop" );
1028 goto internalerr;
1029 }
1030 r->iter[ r->i ].sub = o->field[ s->data ].val[0];
1031 r->iter[ r->i ].end = fp + tlen;
1032 KILLARGS();
1033 break;
1034 case LFMT_LOOP:
1035 if ( r->more ) {
1036 fp = r->loop; /* start over */
1037 tlen = 0; /* care for += tlen */
1038 tok = NULL;
1039 r->occ++;
1040 r->more = 0;
1041 r->i = 0;
1042 goto doneclosing;
1043 }
1044 r->loop = 0;
1045 break;
1046 }
1047
1048 /* close frame, unless it's the outmost */
1049 if ( ! sp )
1050 break;
1051
1052 /* TODO: close loop ? */
1053 s = &stack[ --sp ];
1054
1055 start = s->data + s->pos; /* start of current param in output */
1056 flds = o->len - start; /* # fields for current param */
1057
1058 } while ( CLOSE_IMPL == close );
1059 doneclosing:
1060
1061 if ( NULL == tok )
1062 continue;
1063 if ( ! tok->tag )
1064 goto done;
1065
1066 /* add new token */
1067 if ( NULL == r->loop ) /* open loop ? */
1068 switch ( LFMT_GROUP(tok->tag) ) {
1069 case LFMT_FUNCTIONS:
1070 if ( LFMT_OPEN != tok->tag )
1071 break;
1072 goto openloop; /* else should do, but gcc doesn't grok it right */
1073 case LFMT_LITERAL:
1074 if ( LFMT_COND != tok->tag && LFMT_REP != tok->tag )
1075 break;
1076 case LFMT_ITERATORS:
1077 openloop:
1078 LOG_DBG( LFMT_DBG, "\topening loop on %s", tok->name );
1079 PUSHFRAME( &loop );
1080 s->rec = stack[sp-1].rec; /* inherit record mode */
1081 r->loop = fp;
1082 r->occ = 1;
1083 r->more = 0;
1084 r->had = 0;
1085 r->i = 0;
1086 if ( (s->expl = (LFMT_OPEN == tok->tag)) ) {
1087 r->loop += tlen;
1088 continue;
1089 }
1090 }
1091
1092 if ( tok->sign[2] && LFMT_LITERAL != LFMT_GROUP(tok->tag) ) {
1093 /* token opens standard frame */
1094 if ( LFMT_ITERATORS == LFMT_GROUP(tok->tag) ) {
1095 if ( 1 != r->occ ) { /* not first run */
1096 if ( r->iter[r->i].def != fp ) {
1097 SERR1( "internal error at %d. iterator", r->i + 1 );
1098 goto internalerr;
1099 }
1100 NADD( r->i, LFMT_ITR | r->iter[r->i].tag ); /* push iterator */
1101 fp = r->iter[r->i].end; /* skip parsing */
1102 tlen = 0; /* care for += tlen */
1103 continue; /* next token */
1104 }
1105 if ( LFMT_NITER-1 == r->i ) {
1106 SERR1( "maximum number of iterators %d exceeded", LFMT_NITER );
1107 goto overflow;
1108 }
1109 memset( r->iter + r->i, 0, sizeof(r->iter[0]) );
1110 r->iter[r->i].def = fp;
1111 r->iter[r->i].end = fp + tlen;
1112 }
1113 PUSHFRAME( tok );
1114 switch ( tok->tag ) { /* special treatment */
1115 case LFMT_INDEX:
1116 s->expl = 1;
1117 break;
1118 default:
1119 if ( expl )
1120 s->expl = 1;
1121 }
1122 LOG_DBG( LFMT_DBG, "\topen %s%c%s id %x",
1123 s->tok->name, s->expl?'(':' ', s->tok->sign, s->tok->tag );
1124 }
1125
1126 if ( lit.tag ) { /* a literal */
1127 if ( NULL != lit.val ) { /* string literal */
1128 switch ( lit.tag ) {
1129 case -LFMT_COND:
1130 if ( r->i ? !r->more : r->occ > 1 )
1131 continue;
1132 break;
1133 case -LFMT_REP:
1134 if ( r->i && !r->had )
1135 continue;
1136 break;
1137 }
1138 ADD( lit.tag, lit.val, lit.len );
1139 LOG_DBG( LFMT_DBG, "\tlit %s%.*s id %x",
1140 tok->name, lit.len, lit.val, tok->tag );
1141 } else { /* numeric literal */
1142 NADD( lit.len, lit.tag );
1143 LOG_DBG( LFMT_DBG, "\tlit %d", lit.len );
1144 }
1145 /* new implicit frame immediatly closed by literal ?
1146 problem are implicit loops
1147 if ( o->len == s->data + 1 && ! s->expl ) {
1148 tok = NULL;
1149 goto closeframe;
1150 }
1151 */
1152 } else switch ( tok->tag ) { /* other special tokens */
1153 case LFMT_MDL: f->mode = LFMT_MD; f->upcase = 0; break;
1154 case LFMT_MDU: f->mode = LFMT_MD; f->upcase = 1; break;
1155 case LFMT_MHL: f->mode = LFMT_MH; f->upcase = 0; break;
1156 case LFMT_MHU: f->mode = LFMT_MH; f->upcase = 1; break;
1157 case LFMT_MPL: f->mode = LFMT_MP; f->upcase = 0; break;
1158 case LFMT_MPU: f->mode = LFMT_MP; f->upcase = 1; break;
1159 }
1160
1161 } /* for token */
1162
1163 broken:
1164 internalerr:
1165 overflow:
1166 outofmem:
1167 done:
1168 if ( NULL != o ) {
1169 int i = o->len;
1170 while ( i-- )
1171 if ( NULL == o->field[i].val ) {
1172 ;
1173 } else if ( -LFMT_LIT >= o->field[i].tag )
1174 o->field[i].tag = 0;
1175 }
1176 return o;
1177 } /* rFmt */

  ViewVC Help
Powered by ViewVC 1.1.26