25 #include <qvaluelist.h>
39 #define ENABLE_TRACING 0
42 #define TRACE(x) printf x
51 static QValueList<QCString>
split(
const QCString &str,
const QCString &sep,
52 bool allowEmptyEntries=FALSE,
bool cleanup=TRUE)
54 QValueList<QCString> lst;
57 int i = str.find( sep, j );
61 if ( str.mid(j,i-j).length() > 0 )
65 lst.append(str.mid(j,i-j).stripWhiteSpace());
69 lst.append(str.mid(j,i-j));
72 else if (allowEmptyEntries)
80 int l = str.length() - 1;
81 if (str.mid(j,l-j+1).length()>0)
85 lst.append(str.mid(j,l-j+1).stripWhiteSpace());
89 lst.append(str.mid(j,l-j+1));
92 else if (allowEmptyEntries)
108 const char *p=result.data();
109 char *q = result.rawData();
117 while (*t==
' ' || *t==
'=') {
if (*t++==
'=') found=TRUE; }
126 if (q<p) result.resize(q-result.data()+1);
133 static QCString replace(
const char *s,
char csrc,
char cdst)
136 for (
char *p=result.data();*p;p++)
138 if (*p==csrc) *p=cdst;
148 : m_type(Struct), m_strukt(s), m_raw(FALSE)
154 : m_type(List), m_list(l), m_raw(FALSE)
166 : m_type(v.m_type), m_strukt(0), m_raw(FALSE)
204 else if (tmpType==
List && tmpList ) tmpList->
release();
212 case None:
return FALSE;
246 {
fields.setAutoDelete(TRUE); }
387 if (m_index<0 || m_it==m_list.p->elems.end())
400 QValueList<TemplateVariant>::ConstIterator
m_it;
411 if (index>=0 && index<(
int)
p->
elems.count())
456 case Or:
return "or";
457 case And:
return "and";
458 case Not:
return "not";
459 case In:
return "in";
460 case Equal:
return "==";
462 case Less:
return "<";
466 case Plus:
return "+";
467 case Minus:
return "-";
472 case Colon:
return ":";
473 case Comma:
return ",";
476 case Last:
return "?";
528 int i=(!ext.isEmpty() && ext.at(0)==
'.') ? 1 : 0;
559 QCString
recode(
const QCString &s);
560 void warn(
const char *fileName,
int line,
const char *fmt,...)
const;
565 void addIndexEntry(
const QCString &indexName,
const QValueList<TemplateKeyValue> &arguments);
598 return isInt ? v.
toInt() : 0;
610 if (lhsIsInt && rhsIsInt)
612 return lhsValue+rhsValue;
884 return qstrcmp(item1->
key,item2->
key);
906 sortList.append(
new ListElem(sortKey,item));
916 QListIterator<ListElem> sit(sortList);
918 for (sit.toFirst();(elem=sit.current());++sit)
932 while ((i=arg.find(
"{{",p))!=-1)
934 result+=arg.mid(p,i-p);
935 int j=arg.find(
"}}",i+2);
938 QCString var = arg.mid(i+2,j-i-2);
949 result+=arg.right(arg.length()-p);
972 return qstrcmp(item1->
key,item2->
key);
994 sortList.append(
new ListElem(sortKey,item));
1004 QListIterator<ListElem> sit(sortList);
1008 for (sit.toFirst();(elem=sit.current());++sit)
1010 if (groupList==0 || elem->
key!=prevKey)
1013 result->
append(groupList);
1014 prevKey = elem->
key;
1061 int pageSize = args.
toInt();
1073 result->
append(pageList);
1112 return item1->
key-item2->
key;
1117 return QString(QChar(startLetter)).utf8();
1122 if ((startLetter>=
'0' && startLetter<=
'9') ||
1123 (startLetter>=
'a' && startLetter<=
'z') ||
1124 (startLetter>=
'A' && startLetter<=
'Z'))
1127 if (startLetter>=
'0' && startLetter<=
'9') s[i++] =
'x';
1128 s[i++]=tolower((
char)startLetter);
1133 const char hex[]=
"0123456789abcdef";
1136 if (startLetter>(1<<24))
1138 s[i++]=hex[(startLetter>>28)&0xf];
1139 s[i++]=hex[(startLetter>>24)&0xf];
1141 if (startLetter>(1<<16))
1143 s[i++]=hex[(startLetter>>20)&0xf];
1144 s[i++]=hex[(startLetter>>16)&0xf];
1146 if (startLetter>(1<<8))
1148 s[i++]=hex[(startLetter>>12)&0xf];
1149 s[i++]=hex[(startLetter>>8)&0xf];
1152 s[i++]=hex[(startLetter>>4)&0xf];
1153 s[i++]=hex[(startLetter>>0)&0xf];
1184 sortList.append(
new ListElem(sortKey,item));
1195 QListIterator<ListElem> sit(sortList);
1199 for (sit.toFirst();(elem=sit.current());++sit)
1201 if (letter!=elem->
key || indexNode==0)
1208 indexNode->
set(
"items",indexList);
1209 result->
append(indexNode);
1233 int i=result.findRev(
'/');
1236 result=result.mid(i+1);
1238 i=result.findRev(
'\\');
1241 result=result.mid(i+1);
1306 if (!s.isEmpty() && s.at(0)==
'!')
return TRUE;
1323 if (!s.isEmpty() && s.at(0)==
'^')
return TRUE;
1344 if (!s.isEmpty() && (s.at(0)==
'^' || s.at(0)==
'!'))
1375 return (*func)(v,arg);
1444 {
TRACE((
"ExprAstNumber(%d)\n",num)); }
1456 {
TRACE((
"ExprAstVariable(%s)\n",name)); }
1477 {
TRACE((
"ExprAstFunctionVariable()\n"));
1478 m_args.setAutoDelete(TRUE);
1486 QValueList<TemplateVariant> args;
1487 for (uint i=0;i<
m_args.count();i++)
1509 {
TRACE((
"ExprAstFilter(%s)\n",name)); }
1515 if (ci==0)
return v;
1538 {
TRACE((
"ExprAstFilterAppl\n")); }
1554 {
TRACE((
"ExprAstLiteral(%s)\n",lit)); }
1566 {
TRACE((
"ExprAstNegate\n")); }
1586 return -exp.
toInt();
1670 int denom = rhs.
toInt();
1677 ci->
warn(ci->
templateName(),ci->
line(),
"division by zero while evaluating expression is undefined");
1683 int denom = rhs.
toInt();
1690 ci->
warn(ci->
templateName(),ci->
line(),
"modulo zero while evaluating expression is undefined");
1728 const QCString &
templateName,QList<TemplateToken> &tokens);
1730 QList<TemplateNode> &nodes);
1737 void warn(
const char *fileName,
int line,
const char *fmt,...)
const;
1761 if (expr==0)
return 0;
1997 TRACE((
"}parseNumber()\n"));
2006 TRACE((
"}parseIdentifier()\n"));
2015 TRACE((
"}parseLiteral()\n"));
2030 QList<ExprAst> args;
2031 args.append(argExpr);
2037 args.append(argExpr);
2042 TRACE((
"}parseIdentifierOptionalArgs()\n"));
2048 TRACE((
"{parseFilteredVariable()\n"));
2061 TRACE((
"}parseFilteredVariable()\n"));
2078 TRACE((
"}parseFilter()\n"));
2088 if (p==0 || *p==
'\0')
return FALSE;
2089 while (*p==
' ') p++;
2100 if (c==
'=' && *(p+1)==
'=')
2107 if (c==
'!' && *(p+1)==
'=')
2114 if (c==
'<' && *(p+1)==
'=')
2126 if (c==
'>' && *(p+1)==
'=')
2178 if (strncmp(p,
"not ",4)==0)
2185 if (strncmp(p,
"and ",4)==0)
2192 if (strncmp(p,
"or ",3)==0)
2207 if (c>=
'0' && c<=
'9')
2212 while (*np>=
'0' && *np<=
'9')
2220 else if (c==
'_' || (c>=
'a' && c<=
'z') || (c>=
'A' && c<=
'Z'))
2227 (c==
'_' || c==
'.' ||
2228 (c>=
'a' && c<=
'z') ||
2229 (c>=
'A' && c<=
'Z') ||
2248 else if (c==
'"' || c==
'\'')
2255 while ((c=*p) && (c!=tokenChar || (c==tokenChar && cp==
'\\')))
2258 if (c!=
'\\' || cp==
'\\')
2265 if (*p==tokenChar) p++;
2312 setAutoDelete(TRUE);
2316 TRACE((
"{TemplateNodeList::render\n"));
2317 QListIterator<TemplateNode> it(*
this);
2319 for (it.toFirst();(tn=it.current());++it)
2323 TRACE((
"}TemplateNodeList::render\n"));
2334 const QCString &extension);
2368 : m_engine(e), m_templateName(
"<unknown>"), m_line(1), m_activeEscapeIntf(0),
2369 m_spacelessIntf(0), m_spacelessEnabled(FALSE), m_tabbingEnabled(FALSE), m_indices(
TemplateStruct::alloc())
2398 warn(templateName,line,
"unsupported character conversion: '%s'->'UTF-8'\n", enc.data());
2407 int iSize = s.length();
2408 int oSize = iSize*4+1;
2409 QCString output(oSize);
2410 size_t iLeft = iSize;
2411 size_t oLeft = oSize;
2412 char *iPtr = s.rawData();
2413 char *oPtr = output.rawData();
2416 oSize -= (int)oLeft;
2417 output.resize(oSize+1);
2418 output.at(oSize)=
'\0';
2439 int i=name.find(
'.');
2446 QCString objName = name.left(i);
2448 QCString propName = name.mid(i+1);
2449 while (!propName.isEmpty())
2454 i = propName.find(
".");
2455 int l = i==-1 ? propName.length() : i;
2459 warn(
m_templateName,
m_line,
"requesting non-existing property '%s' for object '%s'",propName.left(l).data(),objName.data());
2463 objName = propName.left(i);
2464 propName = propName.mid(i+1);
2473 i = propName.find(
".");
2474 int l = i==-1 ? propName.length() : i;
2476 int index = propName.left(l).toInt(&b);
2488 propName = propName.mid(i+1);
2508 QDict<TemplateVariant> *dict;
2509 for (it.toFirst();(dict=it.current());++it)
2525 QDict<TemplateVariant> *dict =
new QDict<TemplateVariant>;
2526 dict->setAutoDelete(TRUE);
2547 va_warn(fileName,line,fmt,args);
2555 QStack<TemplateVariant> *stack =
m_indexStacks.find(indexName);
2568 entry->
set(
"children",list);
2569 entry->
set(
"is_leaf_node",
false);
2576 QStack<TemplateVariant> *stack =
m_indexStacks.find(indexName);
2577 if (!stack || stack->count()<3)
2585 delete stack->pop();
2586 delete stack->pop();
2590 delete stack->pop();
2594 entry->
set(
"is_leaf_node",
true);
2621 QValueListConstIterator<TemplateKeyValue> it = arguments.begin();
2629 QStack<TemplateVariant> *stack =
m_indexStacks.find(indexName);
2632 stack =
new QStack<TemplateVariant>;
2633 stack->setAutoDelete(TRUE);
2637 if (stack->isEmpty())
2648 delete stack->pop();
2654 if (stack->count()>1)
2664 list =
dynamic_cast<TemplateList*
>(stack->top()->toList());
2668 for (it=arguments.begin();it!=arguments.end();++it)
2670 entry->
set((*it).key,(*it).value);
2672 if (list->
count()>0)
2675 lastEntry->
set(
"last",
false);
2677 entry->
set(
"is_leaf_node",
true);
2678 entry->
set(
"first",list->
count()==0);
2680 entry->
set(
"parent",parent);
2682 entry->
set(
"last",
true);
2696 TRACE((
"TemplateNodeText('%s')\n",replace(data,
'\n',
' ').data()));
2740 TRACE((
"TemplateNodeVariable(%s)\n",var.data()));
2763 v = v.
call(QValueList<TemplateVariant>());
2810 const QCString &data)
2812 return new T(parser,parent,line,data);
2817 while (root && root->
parent())
2826 int i=fileName.find(
'/');
2832 rootDir.setPath(QDir::currentDirPath());
2833 if (!rootDir.mkdir(outputDir))
2835 err(
"tag OUTPUT_DIRECTORY: Output directory `%s' does not "
2836 "exist and cannot be created\n",outputDir.data());
2839 d.setPath(outputDir);
2846 bool ok = d.mkdir(fileName.mid(j,i-j));
2848 QCString dirName = outputDir+
'/'+fileName.left(i);
2852 i=fileName.find(
'/',i+1);
2869 TRACE((
"{TemplateNodeIf(%s)\n",data.data()));
2875 stopAt.append(
"endif");
2876 stopAt.append(
"elif");
2877 stopAt.append(
"else");
2882 guardedNodes->
line = line;
2889 while (tok && tok->
data.left(5)==
"elif ")
2903 if (tok && tok->
data==
"else")
2905 stopAt.removeLast();
2906 stopAt.removeLast();
2911 TRACE((
"}TemplateNodeIf(%s)\n",data.data()));
2923 bool processed=FALSE;
2926 for (li.toFirst();(nodes=li.current()) && !processed;++li)
2969 TRACE((
"{TemplateNodeRepeat(%s)\n",data.data()));
2973 stopAt.append(
"endrepeat");
2976 TRACE((
"}TemplateNodeRepeat(%s)\n",data.data()));
2990 int i, n = v.
toInt();
2994 s->
set(
"counter0", (
int)i);
2995 s->
set(
"counter", (
int)(i+1));
2996 s->
set(
"revcounter", (
int)(n-i));
2997 s->
set(
"revcounter0", (
int)(n-i-1));
2998 s->
set(
"first",i==0);
2999 s->
set(
"last", i==n-1);
3000 c->
set(
"repeatloop",s.
get());
3024 TRACE((
"{TemplateNodeRange(%s)\n",data.data()));
3026 int i1 = data.find(
" from ");
3027 int i2 = data.find(
" to ");
3028 int i3 = data.find(
" downto ");
3031 if (data.right(5)==
" from")
3035 else if (data==
"from")
3044 else if (i2==-1 && i3==-1)
3046 if (data.right(3)==
" to")
3050 else if (data.right(7)==
" downto")
3052 parser->
warn(
m_templateName,line,
"range is missing end value after 'downto' keyword");
3061 m_var = data.left(i1).stripWhiteSpace();
3062 if (
m_var.isEmpty())
3066 start = data.mid(i1+6,i2-i1-6).stripWhiteSpace();
3069 end = data.right(data.length()-i2-4).stripWhiteSpace();
3074 end = data.right(data.length()-i3-8).stripWhiteSpace();
3083 stopAt.append(
"endrange");
3086 TRACE((
"}TemplateNodeRange(%s)\n",data.data()));
3110 int l =
m_down ? s-e+1 : e-s+1;
3123 s->
set(
"counter0", (
int)index);
3124 s->
set(
"counter", (
int)(index+1));
3125 s->
set(
"revcounter", (
int)(l-index));
3126 s->
set(
"revcounter0", (
int)(l-index-1));
3127 s->
set(
"first",index==0);
3128 s->
set(
"last", (
int)index==l-1);
3130 c->
set(
"forloop",s.
get());
3155 s,
m_down?
"downto":
"to",e);
3194 TRACE((
"{TemplateNodeFor(%s)\n",data.data()));
3196 int i = data.find(
" in ");
3199 if (data.right(3)==
" in")
3203 else if (data==
"in")
3220 int j = data.find(
" reversed",i);
3223 if (j==-1) j=data.length();
3226 exprStr = data.mid(i+4,j-i-4);
3228 if (exprStr.isEmpty())
3237 stopAt.append(
"endfor");
3238 stopAt.append(
"empty");
3241 if (tok && tok->
data==
"empty")
3243 stopAt.removeLast();
3248 TRACE((
"}TemplateNodeFor(%s)\n",data.data()));
3268 v = v.
call(QValueList<TemplateVariant>());
3273 uint listSize = list->
count();
3290 s->
set(
"counter0", (
int)index);
3291 s->
set(
"counter", (
int)(index+1));
3292 s->
set(
"revcounter", (
int)(listSize-index));
3293 s->
set(
"revcounter0", (
int)(listSize-index-1));
3294 s->
set(
"first",index==0);
3295 s->
set(
"last", index==listSize-1);
3297 c->
set(
"forloop",s.
get());
3309 for (uint i=0;i<
m_vars.count();i++,vi++)
3314 for (;vi<
m_vars.count();vi++)
3351 TRACE((
"{TemplateNodeMsg()\n"));
3353 stopAt.append(
"endmsg");
3356 TRACE((
"}TemplateNodeMsg()\n"));
3387 TRACE((
"{TemplateNodeBlock(%s)\n",data.data()));
3394 stopAt.append(
"endblock");
3397 TRACE((
"}TemplateNodeBlock(%s)\n",data.data()));
3417 if (sb && sb!=nb && sb!=
this)
3428 ci->
set(
"block",superBlock.
get());
3465 TRACE((
"{TemplateNodeExtend(%s)\n",data.data()));
3474 TRACE((
"}TemplateNodeExtend(%s)\n",data.data()));
3489 if (extendFile.isEmpty())
3506 QListIterator<TemplateNode> li(
m_nodes);
3508 for (li.toFirst();(n=li.current());++li)
3523 baseTemplate->
render(ts,c);
3548 TRACE((
"TemplateNodeInclude(%s)\n",data.data()));
3568 if (includeFile.isEmpty())
3581 incTemplate->
render(ts,c);
3586 ci->
warn(
m_templateName,
m_line,
"failed to load template '%s' for include",includeFile.data()?includeFile.data():
"");
3601 const char *src = s.data();
3604 char *dst = s.data();
3606 bool skipSpaces=TRUE;
3609 if (c==
'\n') { *dst++=c; skipSpaces=TRUE; }
3610 else if (c==
' ' && skipSpaces) {}
3611 else { *dst++=c; skipSpaces=FALSE; }
3624 TRACE((
"TemplateNodeCreate(%s)\n",data.data()));
3630 int i = data.find(
" from ");
3633 if (data.right(3)==
" from")
3635 parser->
warn(
m_templateName,line,
"create is missing template name after 'from' keyword");
3637 else if (data==
"from")
3667 if (templateFile.isEmpty())
3671 else if (outputFile.isEmpty())
3680 QCString extension=outputFile;
3681 int i=extension.findRev(
'.');
3684 extension=extension.right(extension.length()-i-1);
3697 QFile f(outputFile);
3698 if (f.open(IO_WriteOnly))
3705 createTemplate->
render(os,c);
3748 TRACE((
"{TemplateNodeTree(%s)\n",data.data()));
3756 stopAt.append(
"endrecursetree");
3759 TRACE((
"}TemplateNodeTree(%s)\n",data.data()));
3776 if (ci==0)
return QCString();
3784 c->
set(
"node",node);
3785 bool hasChildren=FALSE;
3793 if (list && list->
count()>0)
3798 c->
set(
"children",children);
3820 return result.data();
3862 TRACE((
"{TemplateNodeIndexEntry(%s)\n",data.data()));
3863 m_args.setAutoDelete(TRUE);
3865 QValueList<QCString> args =
split(data,
" ");
3866 QValueListIterator<QCString> it = args.begin();
3867 if (it==args.end() || (*it).find(
'=')!=-1)
3869 parser->
warn(parser->
templateName(),line,
"Missing name for indexentry tag");
3875 while (it!=args.end())
3878 int j=arg.find(
'=');
3889 parser->
warn(parser->
templateName(),line,
"invalid argument '%s' for indexentry tag",arg.data());
3894 TRACE((
"}TemplateNodeIndexEntry(%s)\n",data.data()));
3903 QListIterator<Mapping> it(
m_args);
3905 QValueList<TemplateKeyValue> list;
3906 for (it.toFirst();(mapping=it.current());++it)
3927 TRACE((
"{TemplateNodeOpenSubIndex(%s)\n",data.data()));
3928 m_name = data.stripWhiteSpace();
3931 parser->
warn(parser->
templateName(),line,
"Missing argument for opensubindex tag");
3933 else if (
m_name.find(
' ')!=-1)
3935 parser->
warn(parser->
templateName(),line,
"Expected single argument for opensubindex tag got '%s'",data.data());
3938 TRACE((
"}TemplateNodeOpenSubIndex(%s)\n",data.data()));
3963 TRACE((
"{TemplateNodeCloseSubIndex(%s)\n",data.data()));
3964 m_name = data.stripWhiteSpace();
3967 parser->
warn(parser->
templateName(),line,
"Missing argument for closesubindex tag");
3971 parser->
warn(parser->
templateName(),line,
"Expected single argument for closesubindex tag got '%s'",data.data());
3974 TRACE((
"}TemplateNodeCloseSubIndex(%s)\n",data.data()));
4007 TRACE((
"{TemplateNodeWith(%s)\n",data.data()));
4008 m_args.setAutoDelete(TRUE);
4011 QValueList<QCString> args =
split(filteredData,
" ");
4012 QValueListIterator<QCString> it = args.begin();
4013 while (it!=args.end())
4016 int j=arg.find(
'=');
4027 parser->
warn(parser->
templateName(),line,
"invalid argument '%s' for 'with' tag",arg.data());
4032 stopAt.append(
"endwith");
4035 TRACE((
"}TemplateNodeWith(%s)\n",data.data()));
4046 QListIterator<Mapping> it(
m_args);
4048 for (it.toFirst();(mapping=it.current());++it)
4070 TRACE((
"{TemplateNodeCycle(%s)\n",data.data()));
4071 m_args.setAutoDelete(TRUE);
4074 QValueList<QCString> args =
split(data,
" ");
4075 QValueListIterator<QCString> it = args.begin();
4076 while (it!=args.end())
4087 parser->
warn(parser->
templateName(),line,
"expected at least two arguments for cycle command, got %d",
m_args.count());
4089 TRACE((
"}TemplateNodeCycle(%s)\n",data.data()));
4100 v = v.
call(QValueList<TemplateVariant>());
4151 TRACE((
"{TemplateNodeSet(%s)\n",data.data()));
4154 int j=data.find(
'=');
4156 if (j>0 && (expr = expParser.
parse(data.mid(j+1))))
4160 TRACE((
"}TemplateNodeSet(%s)\n",data.data()));
4190 TRACE((
"{TemplateNodeSpaceless()\n"));
4192 stopAt.append(
"endspaceless");
4195 TRACE((
"}TemplateNodeSpaceless()\n"));
4220 TRACE((
"{TemplateNodeMarkers(%s)\n",data.data()));
4221 int i = data.find(
" in ");
4222 int w = data.find(
" with ");
4223 if (i==-1 || w==-1 || w<i)
4225 parser->
warn(
m_templateName,line,
"markers tag as wrong format. Expected: markers <var> in <list> with <string_with_markers>");
4230 m_var = data.left(i);
4235 stopAt.append(
"endmarkers");
4238 TRACE((
"}TemplateNodeMarkers(%s)\n",data.data()));
4261 QCString str = patternStr.
toString();
4262 QRegExp marker(
"@[0-9]+");
4263 int index=0,newIndex,matchLen;
4264 while ((newIndex=marker.match(str,index,&matchLen))!=-1)
4268 ts << ci->
recode(str.mid(index,newIndex-index));
4272 ts << str.mid(index,newIndex-index);
4275 uint entryIndex = str.mid(newIndex+1,matchLen-1).toUInt(&ok);
4279 for (it->
toFirst(); (it->
current(var)) && i<entryIndex; it->toNext(),i++) {}
4280 if (ok && i==entryIndex)
4283 s->
set(
"id",(
int)i);
4284 c->
set(
"markers",s.
get());
4295 else if (i<entryIndex)
4299 index=newIndex+matchLen;
4303 ts << ci->
recode(str.right(str.length()-index));
4307 ts << str.right(str.length()-index);
4339 TRACE((
"{TemplateNodeTabbing()\n"));
4341 stopAt.append(
"endtabbing");
4344 TRACE((
"}TemplateNodeTabbing()\n"));
4369 TRACE((
"{TemplateNodeResource(%s)\n",data.data()));
4378 else if ((i=data.find(
" as "))!=-1)
4388 TRACE((
"}TemplateNodeResource(%s)\n",data.data()));
4403 if (resourceFile.isEmpty())
4414 if (targetFile.isEmpty())
4443 TRACE((
"{TemplateNodeEncoding(%s)\n",data.data()));
4455 stopAt.append(
"endencoding");
4458 TRACE((
"}TemplateNodeEncoding(%s)\n",data.data()));
4474 QCString oldEncStr = ci->
encoding();
4475 if (!encStr.isEmpty())
4496 const QCString &data);
4509 const QCString &data)
4566 QList<TemplateNodeBlock> *list =
m_blocks.find(name);
4567 if (list==0 || list->count()==0)
4573 return list->getLast();
4579 QList<TemplateNodeBlock> *list =
m_blocks.find(name);
4580 if (list==0 || list->count()==0)
4586 return list->take(list->count()-1);
4592 QList<TemplateNodeBlock> *list =
m_blocks.find(block->
name());
4595 list =
new QList<TemplateNodeBlock>;
4598 list->prepend(block);
4603 QDictIterator< QList<TemplateNodeBlock> > di(ctx->
m_blocks);
4604 QList<TemplateNodeBlock> *list;
4605 for (di.toFirst();(list=di.current());++di)
4607 QListIterator<TemplateNodeBlock> li(*list);
4609 for (li.toFirst();(nb=li.current());++li)
4623 QList<TemplateNodeBlock> *list =
m_blocks.find(block->
name());
4626 list =
new QList<TemplateNodeBlock>;
4629 list->append(block);
4640 void tokenize(QList<TemplateToken> &tokens);
4644 void addToken(QList<TemplateToken> &tokens,
4645 const char *data,
int line,
int startPos,
int endPos,
4656 m_engine(engine), m_fileName(fileName), m_data(data)
4677 const char *p=
m_data.data();
4679 int state=StateText;
4683 bool emptyOutputLine=TRUE;
4686 int markStartPos=-1;
4687 for (;(c=*p);p++,pos++)
4694 state=StateBeginTemplate;
4696 else if (c!=
' ' && c!=
'\t' && c!=
'\n')
4698 emptyOutputLine=FALSE;
4701 case StateBeginTemplate:
4715 state=StateMaybeVar;
4719 state=StateVariable;
4725 emptyOutputLine=FALSE;
4746 emptyOutputLine ? startLinePos : markStartPos,
4750 lastTokenPos = pos+1;
4770 state=StateEndComment;
4773 case StateEndComment:
4779 emptyOutputLine ? startLinePos : markStartPos,
4781 lastTokenPos = pos+1;
4805 state=StateVariable;
4810 emptyOutputLine=FALSE;
4818 state=StateEndVariable;
4821 case StateEndVariable:
4827 emptyOutputLine ? startLinePos : markStartPos,
4831 lastTokenPos = pos+1;
4840 state=StateVariable;
4850 if (markStartPos!=-1 && emptyOutputLine) lastTokenPos = startLinePos;
4854 emptyOutputLine=TRUE;
4857 if (lastTokenPos<pos)
4866 const char *data,
int line,
4867 int startPos,
int endPos,
4870 if (startPos<endPos)
4872 int len = endPos-startPos+1;
4874 qstrncpy(text.rawData(),data+startPos,len);
4883 const QCString &templateName,
4884 QList<TemplateToken> &tokens) :
4885 m_engine(engine), m_templateName(templateName), m_tokens(tokens)
4891 QList<TemplateNode> &nodes)
4893 TRACE((
"{TemplateParser::parse\n"));
4910 QCString command = tok->
data;
4911 int sep = command.find(
' ');
4914 command=command.left(sep);
4916 if (stopAt.contains(command))
4919 TRACE((
"}TemplateParser::parse: stop\n"));
4925 arg = tok->
data.mid(sep+1);
4928 create(command,
this,parent,tok->
line,arg);
4933 else if (command==
"empty" || command==
"else" ||
4934 command==
"endif" || command==
"endfor" ||
4935 command==
"endblock" || command==
"endwith" ||
4936 command==
"endrecursetree" || command==
"endspaceless" ||
4937 command==
"endmarkers" || command==
"endmsg" ||
4938 command==
"endrepeat" || command==
"elif" ||
4939 command==
"endrange" || command==
"endtabbing" ||
4940 command==
"endencoding")
4953 if (!stopAt.isEmpty())
4955 QStrListIterator it(stopAt);
4958 for (it.toFirst();(s=it.current());++it)
4960 if (!options.isEmpty()) options+=
", ";
4966 TRACE((
"}TemplateParser::parse: last token\n"));
4998 va_warn(fileName,line,fmt,args);
5009 const QCString &extension)
5015 if (extension==
"tex")
5019 QList<TemplateToken> tokens;
5020 tokens.setAutoDelete(TRUE);
5041 QListIterator<TemplateNode> li(
m_nodes);
5043 for (li.toFirst();(n=li.current());++li)
5095 if (f.open(IO_ReadOnly))
5097 QFileInfo fi(filePath);
5099 QCString data(size+1);
5100 if (f.readBlock(data.rawData(),size)==size)
5109 if (!data.isEmpty())
5116 err(
"Cound not open template file %s\n",fileName.data());
5130 void enterBlock(
const QCString &fileName,
const QCString &blockName,
int line)
5151 while ((ie=li.current()))
5159 warn(fileName,line,
" inside template '%s' included from template '%s' at line %d",ie->
fileName().data(),next->
fileName().data(),ie->
line());
5164 warn(fileName,line,
" included by block '%s' inside template '%s' at line %d",ie->
blockName().data(),