14a63fecaSMasatake YAMATO /*
24a63fecaSMasatake YAMATO *
34a63fecaSMasatake YAMATO * Copyright (c) 2015, Red Hat, Inc.
44a63fecaSMasatake YAMATO * Copyright (c) 2015, Masatake YAMATO
54a63fecaSMasatake YAMATO *
64a63fecaSMasatake YAMATO * Author: Masatake YAMATO <yamato@redhat.com>
74a63fecaSMasatake YAMATO *
84a63fecaSMasatake YAMATO * This source code is released for free distribution under the terms of the
94a63fecaSMasatake YAMATO * GNU General Public License version 2 or (at your option) any later version.
104a63fecaSMasatake YAMATO *
114a63fecaSMasatake YAMATO */
124a63fecaSMasatake YAMATO
134a63fecaSMasatake YAMATO #include "general.h"
1444fdd1c7SMasatake YAMATO #include "debug.h"
158cbf052bSMasatake YAMATO #include "entry_p.h"
16d45725c1SMasatake YAMATO #include "fmt_p.h"
174a63fecaSMasatake YAMATO #include "field.h"
18c08c70d0SMasatake YAMATO #include "field_p.h"
198f2569d8SMasatake YAMATO #include "parse.h"
204a63fecaSMasatake YAMATO #include "routines.h"
214a63fecaSMasatake YAMATO #include <string.h>
224a63fecaSMasatake YAMATO #include <errno.h>
234a63fecaSMasatake YAMATO
244a63fecaSMasatake YAMATO typedef union uFmtSpec {
254a63fecaSMasatake YAMATO char *const_str;
264a63fecaSMasatake YAMATO struct {
27efae38f9SMasatake YAMATO fieldType ftype;
284a63fecaSMasatake YAMATO int width;
29830b3c66SMasatake YAMATO char *raw_fmtstr;
304a63fecaSMasatake YAMATO } field;
314a63fecaSMasatake YAMATO } fmtSpec;
324a63fecaSMasatake YAMATO
334a63fecaSMasatake YAMATO struct sFmtElement {
344a63fecaSMasatake YAMATO union uFmtSpec spec;
35509a47dbSJiří Techet int (* printer) (fmtSpec*, MIO* fp, const tagEntryInfo *);
364a63fecaSMasatake YAMATO struct sFmtElement *next;
374a63fecaSMasatake YAMATO };
384a63fecaSMasatake YAMATO
printLiteral(fmtSpec * fspec,MIO * fp,const tagEntryInfo * tag CTAGS_ATTR_UNUSED)398ccb7ee9SJiří Techet static int printLiteral (fmtSpec* fspec, MIO* fp, const tagEntryInfo * tag CTAGS_ATTR_UNUSED)
404a63fecaSMasatake YAMATO {
41509a47dbSJiří Techet return mio_puts (fp, fspec->const_str);
424a63fecaSMasatake YAMATO }
434a63fecaSMasatake YAMATO
isParserFieldCompatibleWithFtype(const tagField * pfield,int baseFtype)44ce990805SThomas Braun static bool isParserFieldCompatibleWithFtype (const tagField *pfield, int baseFtype)
458660d347SMasatake YAMATO {
468660d347SMasatake YAMATO do {
478660d347SMasatake YAMATO if (pfield->ftype == baseFtype)
48ce990805SThomas Braun return true;
498660d347SMasatake YAMATO baseFtype = nextSiblingField (baseFtype);
508660d347SMasatake YAMATO } while (baseFtype != FIELD_UNKNOWN);
51ce990805SThomas Braun return false;
528660d347SMasatake YAMATO }
538660d347SMasatake YAMATO
printTagField(fmtSpec * fspec,MIO * fp,const tagEntryInfo * tag)54509a47dbSJiří Techet static int printTagField (fmtSpec* fspec, MIO* fp, const tagEntryInfo * tag)
554a63fecaSMasatake YAMATO {
564a63fecaSMasatake YAMATO int i;
574a63fecaSMasatake YAMATO int width = fspec->field.width;
5844fdd1c7SMasatake YAMATO int ftype;
59c88e59d9SMasatake YAMATO const char* str = NULL;
6044fdd1c7SMasatake YAMATO
6144fdd1c7SMasatake YAMATO ftype = fspec->field.ftype;
6244fdd1c7SMasatake YAMATO
63546d15f5SMasatake YAMATO if (isCommonField (ftype))
645e272693SMasatake YAMATO str = renderField (ftype, tag, NO_PARSER_FIELD);
65546d15f5SMasatake YAMATO else
6644fdd1c7SMasatake YAMATO {
6744fdd1c7SMasatake YAMATO unsigned int findex;
684e9e52c2SMasatake YAMATO const tagField *f;
6944fdd1c7SMasatake YAMATO
7044fdd1c7SMasatake YAMATO for (findex = 0; findex < tag->usedParserFields; findex++)
7144fdd1c7SMasatake YAMATO {
729353c835SMasatake YAMATO f = getParserFieldForIndex(tag, findex);
734e9e52c2SMasatake YAMATO if (isParserFieldCompatibleWithFtype (f, ftype))
7444fdd1c7SMasatake YAMATO break;
7544fdd1c7SMasatake YAMATO }
7644fdd1c7SMasatake YAMATO
778660d347SMasatake YAMATO if (findex == tag->usedParserFields)
784d5ee6f7SMasatake YAMATO str = "";
794e9e52c2SMasatake YAMATO else if (isFieldEnabled (f->ftype))
80322d6c7bSMasatake YAMATO {
81322d6c7bSMasatake YAMATO unsigned int dt = getFieldDataType (f->ftype);
82322d6c7bSMasatake YAMATO if (dt & FIELDTYPE_STRING)
83322d6c7bSMasatake YAMATO {
845e272693SMasatake YAMATO str = renderField (f->ftype, tag, findex);
85322d6c7bSMasatake YAMATO if ((dt & FIELDTYPE_BOOL) && str[0] == '\0')
86322d6c7bSMasatake YAMATO {
87322d6c7bSMasatake YAMATO /* TODO: FIELD_NULL_LETTER_STRING */
88322d6c7bSMasatake YAMATO str = "-";
89322d6c7bSMasatake YAMATO }
90322d6c7bSMasatake YAMATO }
91322d6c7bSMasatake YAMATO else if (dt & FIELDTYPE_BOOL)
92322d6c7bSMasatake YAMATO str = getFieldName (f->ftype);
93322d6c7bSMasatake YAMATO else
94322d6c7bSMasatake YAMATO {
95322d6c7bSMasatake YAMATO /* Not implemented */
96322d6c7bSMasatake YAMATO AssertNotReached ();
97322d6c7bSMasatake YAMATO str = "CTAGS INTERNAL BUG!";
98322d6c7bSMasatake YAMATO }
99322d6c7bSMasatake YAMATO }
1008660d347SMasatake YAMATO }
1014d5ee6f7SMasatake YAMATO
102c88e59d9SMasatake YAMATO if (str == NULL)
103c88e59d9SMasatake YAMATO str = "";
104c88e59d9SMasatake YAMATO
105830b3c66SMasatake YAMATO if (width)
106830b3c66SMasatake YAMATO i = mio_printf (fp, fspec->field.raw_fmtstr, width, str);
1074a63fecaSMasatake YAMATO else
1084a63fecaSMasatake YAMATO {
109509a47dbSJiří Techet mio_puts (fp, str);
1104a63fecaSMasatake YAMATO i = strlen (str);
1114a63fecaSMasatake YAMATO }
1124a63fecaSMasatake YAMATO return i;
1134a63fecaSMasatake YAMATO }
1144a63fecaSMasatake YAMATO
queueLiteral(fmtElement ** last,char * literal)1154a63fecaSMasatake YAMATO static fmtElement** queueLiteral (fmtElement **last, char *literal)
1164a63fecaSMasatake YAMATO {
1174a63fecaSMasatake YAMATO fmtElement *cur = xMalloc (1, fmtElement);
1184a63fecaSMasatake YAMATO
1194a63fecaSMasatake YAMATO cur->spec.const_str = literal;
1204a63fecaSMasatake YAMATO cur->printer = printLiteral;
1214a63fecaSMasatake YAMATO cur->next = NULL;
1224a63fecaSMasatake YAMATO *last = cur;
1234a63fecaSMasatake YAMATO return &(cur->next);
1244a63fecaSMasatake YAMATO }
1254a63fecaSMasatake YAMATO
1262a2978a3SMasatake YAMATO /* `getLanguageComponentInFieldName' is used as part of the option parameter
1272a2978a3SMasatake YAMATO for --_xformat option.
1282a2978a3SMasatake YAMATO
1292a2978a3SMasatake YAMATO It splits the value of fullName into a language part and a field name part.
1302a2978a3SMasatake YAMATO Here the two parts are combined with `.'.
1312a2978a3SMasatake YAMATO
1322a2978a3SMasatake YAMATO If it cannot find a period, it returns LANG_IGNORE and sets
1332a2978a3SMasatake YAMATO fullname to *fieldName.
1342a2978a3SMasatake YAMATO
1352a2978a3SMasatake YAMATO If lang part if `*', it returns LANG_AUTO and sets the field
1362a2978a3SMasatake YAMATO name part to *fieldName.
1372a2978a3SMasatake YAMATO
1382a2978a3SMasatake YAMATO Though a period is found but no parser (langType) is found for
1392a2978a3SMasatake YAMATO the language parser, this function returns LANG_IGNORE and sets
1402a2978a3SMasatake YAMATO NULL to *fieldName.
1412a2978a3SMasatake YAMATO
1422a2978a3SMasatake YAMATO A proper parser is found, this function returns langType for the
1432a2978a3SMasatake YAMATO parser and sets the field name part to *fieldName. */
getLanguageComponentInFieldName(const char * fullName,const char ** fieldName)1442a2978a3SMasatake YAMATO static langType getLanguageComponentInFieldName (const char *fullName,
1452a2978a3SMasatake YAMATO const char **fieldName)
1462a2978a3SMasatake YAMATO {
1472a2978a3SMasatake YAMATO const char *tmp;
1482a2978a3SMasatake YAMATO langType language;
1492a2978a3SMasatake YAMATO
1502a2978a3SMasatake YAMATO tmp = strchr (fullName, '.');
1512a2978a3SMasatake YAMATO if (tmp)
1522a2978a3SMasatake YAMATO {
1532a2978a3SMasatake YAMATO size_t len = tmp - fullName;
1542a2978a3SMasatake YAMATO
1552a2978a3SMasatake YAMATO if (len == 1 && fullName[0] == '*')
1562a2978a3SMasatake YAMATO {
1572a2978a3SMasatake YAMATO language = LANG_AUTO;
1582a2978a3SMasatake YAMATO *fieldName = tmp + 1;
1592a2978a3SMasatake YAMATO }
1602a2978a3SMasatake YAMATO else if (len == 0)
1612a2978a3SMasatake YAMATO {
1622a2978a3SMasatake YAMATO language = LANG_IGNORE;
1632a2978a3SMasatake YAMATO *fieldName = tmp + 1;
1642a2978a3SMasatake YAMATO }
1652a2978a3SMasatake YAMATO else
1662a2978a3SMasatake YAMATO {
1672a2978a3SMasatake YAMATO language = getNamedLanguage (fullName, len);
1682a2978a3SMasatake YAMATO if (language == LANG_IGNORE)
1692a2978a3SMasatake YAMATO *fieldName = NULL;
1702a2978a3SMasatake YAMATO else
1712a2978a3SMasatake YAMATO *fieldName = tmp + 1;
1722a2978a3SMasatake YAMATO }
1732a2978a3SMasatake YAMATO }
1742a2978a3SMasatake YAMATO else
1752a2978a3SMasatake YAMATO {
1762a2978a3SMasatake YAMATO language = LANG_IGNORE;
1772a2978a3SMasatake YAMATO *fieldName = fullName;
1782a2978a3SMasatake YAMATO }
1792a2978a3SMasatake YAMATO return language;
1802a2978a3SMasatake YAMATO }
1812a2978a3SMasatake YAMATO
queueTagField(fmtElement ** last,long width,bool truncation,char field_letter,const char * field_name)18218d5414aSMasatake YAMATO static fmtElement** queueTagField (fmtElement **last, long width, bool truncation,
18318d5414aSMasatake YAMATO char field_letter, const char *field_name)
1844a63fecaSMasatake YAMATO {
1854a63fecaSMasatake YAMATO fieldType ftype;
1864a63fecaSMasatake YAMATO fmtElement *cur;
1878f2569d8SMasatake YAMATO langType language;
1884a63fecaSMasatake YAMATO
18944fdd1c7SMasatake YAMATO if (field_letter == NUL_FIELD_LETTER)
1908f2569d8SMasatake YAMATO {
1918f2569d8SMasatake YAMATO const char *f;
1928f2569d8SMasatake YAMATO
1938f2569d8SMasatake YAMATO language = getLanguageComponentInFieldName (field_name, &f);
1948660d347SMasatake YAMATO if (f == NULL)
1958660d347SMasatake YAMATO error (FATAL, "No suitable parser for field name: %s", field_name);
1968f2569d8SMasatake YAMATO ftype = getFieldTypeForNameAndLanguage (f, language);
1978f2569d8SMasatake YAMATO }
19844fdd1c7SMasatake YAMATO else
1998f2569d8SMasatake YAMATO {
2008f2569d8SMasatake YAMATO language = LANG_IGNORE;
2014a63fecaSMasatake YAMATO ftype = getFieldTypeForOption (field_letter);
2028f2569d8SMasatake YAMATO }
20344fdd1c7SMasatake YAMATO
2044a63fecaSMasatake YAMATO if (ftype == FIELD_UNKNOWN)
20544fdd1c7SMasatake YAMATO {
20644fdd1c7SMasatake YAMATO if (field_letter == NUL_FIELD_LETTER)
20744fdd1c7SMasatake YAMATO error (FATAL, "No such field name: %s", field_name);
20844fdd1c7SMasatake YAMATO else
2094a63fecaSMasatake YAMATO error (FATAL, "No such field letter: %c", field_letter);
21044fdd1c7SMasatake YAMATO }
2114a63fecaSMasatake YAMATO
2125e272693SMasatake YAMATO if (!doesFieldHaveRenderer (ftype, false))
21344fdd1c7SMasatake YAMATO {
21444fdd1c7SMasatake YAMATO Assert (field_letter != NUL_FIELD_LETTER);
2154a63fecaSMasatake YAMATO error (FATAL, "The field cannot be printed in format output: %c", field_letter);
21644fdd1c7SMasatake YAMATO }
2174a63fecaSMasatake YAMATO
2184a63fecaSMasatake YAMATO cur = xMalloc (1, fmtElement);
2194a63fecaSMasatake YAMATO
2204a63fecaSMasatake YAMATO cur->spec.field.width = width;
221efae38f9SMasatake YAMATO cur->spec.field.ftype = ftype;
222830b3c66SMasatake YAMATO
223830b3c66SMasatake YAMATO if (width < 0)
224830b3c66SMasatake YAMATO {
225830b3c66SMasatake YAMATO cur->spec.field.width *= -1;
226830b3c66SMasatake YAMATO cur->spec.field.raw_fmtstr = (truncation? "%-.*s": "%-*s");
227830b3c66SMasatake YAMATO }
228830b3c66SMasatake YAMATO else if (width > 0)
229830b3c66SMasatake YAMATO cur->spec.field.raw_fmtstr = (truncation? "%.*s": "%*s");
230830b3c66SMasatake YAMATO else
231830b3c66SMasatake YAMATO cur->spec.field.raw_fmtstr = NULL;
2324a63fecaSMasatake YAMATO
233*c0421c5eSMasatake YAMATO enableField (ftype, true);
2348f2569d8SMasatake YAMATO if (language == LANG_AUTO)
2358f2569d8SMasatake YAMATO {
2368f2569d8SMasatake YAMATO fieldType ftype_next = ftype;
237a6c7c87fSMasatake YAMATO
238a6c7c87fSMasatake YAMATO while ((ftype_next = nextSiblingField (ftype_next)) != FIELD_UNKNOWN)
239*c0421c5eSMasatake YAMATO enableField (ftype_next, true);
2408f2569d8SMasatake YAMATO }
2414a63fecaSMasatake YAMATO
2424a63fecaSMasatake YAMATO cur->printer = printTagField;
2434a63fecaSMasatake YAMATO cur->next = NULL;
2444a63fecaSMasatake YAMATO *last = cur;
2454a63fecaSMasatake YAMATO return &(cur->next);
2464a63fecaSMasatake YAMATO }
2474a63fecaSMasatake YAMATO
fmtNew(const char * fmtString)2484a63fecaSMasatake YAMATO extern fmtElement *fmtNew (const char* fmtString)
2494a63fecaSMasatake YAMATO {
2504a63fecaSMasatake YAMATO int i;
2514a63fecaSMasatake YAMATO vString *literal = NULL;
2524a63fecaSMasatake YAMATO fmtElement *code = NULL;
2534a63fecaSMasatake YAMATO fmtElement **last = &code;
254ce990805SThomas Braun bool found_percent = false;
2554a63fecaSMasatake YAMATO long column_width;
2564a63fecaSMasatake YAMATO const char* cursor;
2574a63fecaSMasatake YAMATO
2584a63fecaSMasatake YAMATO cursor = fmtString;
2594a63fecaSMasatake YAMATO
2604a63fecaSMasatake YAMATO for (i = 0; cursor[i] != '\0'; ++i)
2614a63fecaSMasatake YAMATO {
2624a63fecaSMasatake YAMATO if (found_percent)
2634a63fecaSMasatake YAMATO {
264ce990805SThomas Braun found_percent = false;
2654a63fecaSMasatake YAMATO if (cursor[i] == '%')
2664a63fecaSMasatake YAMATO {
2674a63fecaSMasatake YAMATO if (literal == NULL)
2684a63fecaSMasatake YAMATO literal = vStringNew ();
2694a63fecaSMasatake YAMATO vStringPut (literal, cursor[i]);
2704a63fecaSMasatake YAMATO }
2714a63fecaSMasatake YAMATO else
2724a63fecaSMasatake YAMATO {
2734a63fecaSMasatake YAMATO int justification_right = 1;
27418d5414aSMasatake YAMATO bool truncation = false;
2754a63fecaSMasatake YAMATO vString *width = NULL;
2764a63fecaSMasatake YAMATO if (literal)
2774a63fecaSMasatake YAMATO {
2784a63fecaSMasatake YAMATO char* l = vStringDeleteUnwrap (literal);
2794a63fecaSMasatake YAMATO literal = NULL;
2804a63fecaSMasatake YAMATO last = queueLiteral (last, l);
2814a63fecaSMasatake YAMATO }
2824a63fecaSMasatake YAMATO if (cursor [i] == '-')
2834a63fecaSMasatake YAMATO {
2844a63fecaSMasatake YAMATO justification_right = -1;
2854a63fecaSMasatake YAMATO i++;
2864a63fecaSMasatake YAMATO
2874a63fecaSMasatake YAMATO if (cursor [i] == '\0')
2884a63fecaSMasatake YAMATO error (FATAL, "unexpectedly terminated just after '-': \"%s\"", fmtString);
2894a63fecaSMasatake YAMATO
2904a63fecaSMasatake YAMATO }
29118d5414aSMasatake YAMATO if (cursor [i] == '.')
29218d5414aSMasatake YAMATO {
29318d5414aSMasatake YAMATO truncation = true;
29418d5414aSMasatake YAMATO i++;
29518d5414aSMasatake YAMATO
29618d5414aSMasatake YAMATO if (cursor [i] == '\0')
29718d5414aSMasatake YAMATO error (FATAL, "unexpectedly terminated just after '.': \"%s\"", fmtString);
29818d5414aSMasatake YAMATO }
2994a63fecaSMasatake YAMATO
3004a63fecaSMasatake YAMATO while ( '0' <= cursor[i] && cursor[i] <= '9' )
3014a63fecaSMasatake YAMATO {
3024a63fecaSMasatake YAMATO if (width == NULL)
3034a63fecaSMasatake YAMATO width = vStringNew ();
3044a63fecaSMasatake YAMATO vStringPut (width, cursor[i]);
3054a63fecaSMasatake YAMATO i++;
3064a63fecaSMasatake YAMATO
3074a63fecaSMasatake YAMATO if (cursor [i] == '\0')
3084a63fecaSMasatake YAMATO error (FATAL, "unexpectedly terminated during parsing column width: \"%s\"", fmtString);
3094a63fecaSMasatake YAMATO }
3104a63fecaSMasatake YAMATO
3114a63fecaSMasatake YAMATO if (justification_right == -1 && width == NULL)
3124a63fecaSMasatake YAMATO error (FATAL, "no column width given after '-': \"%s\"", fmtString);
3134a63fecaSMasatake YAMATO
3144a63fecaSMasatake YAMATO column_width = 0;
3154a63fecaSMasatake YAMATO if (width)
3164a63fecaSMasatake YAMATO {
317fa94dd09SThomas Braun if(!strToLong (vStringValue (width), 0, &column_width))
318759d281dSK.Takata error (FATAL | PERROR, "converting failed: %s", vStringValue (width));
3194a63fecaSMasatake YAMATO vStringDelete (width);
3204a63fecaSMasatake YAMATO width = NULL;
3214a63fecaSMasatake YAMATO column_width *= justification_right;
3224a63fecaSMasatake YAMATO }
3234a63fecaSMasatake YAMATO
32444fdd1c7SMasatake YAMATO if (cursor[i] == '{')
32544fdd1c7SMasatake YAMATO {
32644fdd1c7SMasatake YAMATO vString *field_name = vStringNew ();
32744fdd1c7SMasatake YAMATO
32844fdd1c7SMasatake YAMATO i++;
32944fdd1c7SMasatake YAMATO for (; cursor[i] != '}'; i++)
33044fdd1c7SMasatake YAMATO vStringPut (field_name, cursor[i]);
33144fdd1c7SMasatake YAMATO
33218d5414aSMasatake YAMATO last = queueTagField (last, column_width, truncation,
33318d5414aSMasatake YAMATO NUL_FIELD_LETTER, vStringValue (field_name));
33444fdd1c7SMasatake YAMATO
33544fdd1c7SMasatake YAMATO vStringDelete (field_name);
33644fdd1c7SMasatake YAMATO }
33744fdd1c7SMasatake YAMATO else
33818d5414aSMasatake YAMATO last = queueTagField (last, column_width, truncation,
33918d5414aSMasatake YAMATO cursor[i], NULL);
3404a63fecaSMasatake YAMATO }
3414a63fecaSMasatake YAMATO
3424a63fecaSMasatake YAMATO }
3434a63fecaSMasatake YAMATO else
3444a63fecaSMasatake YAMATO {
3454a63fecaSMasatake YAMATO if (cursor[i] == '%')
346ce990805SThomas Braun found_percent = true;
3474a63fecaSMasatake YAMATO else
3484a63fecaSMasatake YAMATO {
3494a63fecaSMasatake YAMATO if (literal == NULL)
3504a63fecaSMasatake YAMATO literal = vStringNew ();
3514a63fecaSMasatake YAMATO
3524a63fecaSMasatake YAMATO vStringPut (literal, cursor[i]);
3534a63fecaSMasatake YAMATO }
3544a63fecaSMasatake YAMATO }
3554a63fecaSMasatake YAMATO }
3564a63fecaSMasatake YAMATO if (literal)
3574a63fecaSMasatake YAMATO {
3584a63fecaSMasatake YAMATO char* l = vStringDeleteUnwrap (literal);
3594a63fecaSMasatake YAMATO literal = NULL;
3604a63fecaSMasatake YAMATO last = queueLiteral (last, l);
3614a63fecaSMasatake YAMATO }
3624a63fecaSMasatake YAMATO return code;
3634a63fecaSMasatake YAMATO }
3644a63fecaSMasatake YAMATO
fmtPrint(fmtElement * fmtelts,MIO * fp,const tagEntryInfo * tag)365509a47dbSJiří Techet extern int fmtPrint (fmtElement * fmtelts, MIO* fp, const tagEntryInfo *tag)
3664a63fecaSMasatake YAMATO {
3674a63fecaSMasatake YAMATO fmtElement *f = fmtelts;
3684a63fecaSMasatake YAMATO int i = 0;
3694a63fecaSMasatake YAMATO while (f)
3704a63fecaSMasatake YAMATO {
3714a63fecaSMasatake YAMATO i += f->printer (&(f->spec), fp, tag);
3724a63fecaSMasatake YAMATO f = f->next;
3734a63fecaSMasatake YAMATO }
3744a63fecaSMasatake YAMATO return i;
3754a63fecaSMasatake YAMATO }
3764a63fecaSMasatake YAMATO
fmtDelete(fmtElement * fmtelts)3774a63fecaSMasatake YAMATO extern void fmtDelete (fmtElement * fmtelts)
3784a63fecaSMasatake YAMATO {
3794a63fecaSMasatake YAMATO fmtElement *f = fmtelts;
3804a63fecaSMasatake YAMATO fmtElement *next;
3814a63fecaSMasatake YAMATO
3824a63fecaSMasatake YAMATO while (f)
3834a63fecaSMasatake YAMATO {
3844a63fecaSMasatake YAMATO next = f->next;
3854a63fecaSMasatake YAMATO if (f->printer == printLiteral)
3864a63fecaSMasatake YAMATO {
3874a63fecaSMasatake YAMATO eFree (f->spec.const_str);
3884a63fecaSMasatake YAMATO f->spec.const_str = NULL;
3894a63fecaSMasatake YAMATO }
3904a63fecaSMasatake YAMATO f->next = NULL;
3914a63fecaSMasatake YAMATO eFree (f);
3924a63fecaSMasatake YAMATO f = next;
3934a63fecaSMasatake YAMATO }
3944a63fecaSMasatake YAMATO }
395