* xmlCompilePathPattern: * @ctxt: the compilation context * * Compile the Path Pattern and generates a precompiled * form suitable for fast matching. * * [5] Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest ) */
| 1213 | * [5] Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest ) |
| 1214 | */ |
| 1215 | static void |
| 1216 | xmlCompilePathPattern(xmlPatParserContextPtr ctxt) { |
| 1217 | SKIP_BLANKS; |
| 1218 | if (CUR == '/') { |
| 1219 | ctxt->comp->flags |= PAT_FROM_ROOT; |
| 1220 | } else if ((CUR == '.') || (ctxt->comp->flags & XML_PATTERN_NOTPATTERN)) { |
| 1221 | ctxt->comp->flags |= PAT_FROM_CUR; |
| 1222 | } |
| 1223 | |
| 1224 | if ((CUR == '/') && (NXT(1) == '/')) { |
| 1225 | PUSH(XML_OP_ANCESTOR, NULL, NULL); |
| 1226 | NEXT; |
| 1227 | NEXT; |
| 1228 | } else if ((CUR == '.') && (NXT(1) == '/') && (NXT(2) == '/')) { |
| 1229 | PUSH(XML_OP_ANCESTOR, NULL, NULL); |
| 1230 | NEXT; |
| 1231 | NEXT; |
| 1232 | NEXT; |
| 1233 | /* Check for incompleteness. */ |
| 1234 | SKIP_BLANKS; |
| 1235 | if (CUR == 0) { |
| 1236 | ERROR5(NULL, NULL, NULL, |
| 1237 | "Incomplete expression '%s'.\n", ctxt->base); |
| 1238 | ctxt->error = 1; |
| 1239 | goto error; |
| 1240 | } |
| 1241 | } |
| 1242 | if (CUR == '@') { |
| 1243 | NEXT; |
| 1244 | xmlCompileAttributeTest(ctxt); |
| 1245 | if (ctxt->error != 0) |
| 1246 | goto error; |
| 1247 | SKIP_BLANKS; |
| 1248 | /* TODO: check for incompleteness */ |
| 1249 | if (CUR != 0) { |
| 1250 | xmlCompileStepPattern(ctxt); |
| 1251 | if (ctxt->error != 0) |
| 1252 | goto error; |
| 1253 | } |
| 1254 | } else { |
| 1255 | if (CUR == '/') { |
| 1256 | PUSH(XML_OP_ROOT, NULL, NULL); |
| 1257 | NEXT; |
| 1258 | /* Check for incompleteness. */ |
| 1259 | SKIP_BLANKS; |
| 1260 | if (CUR == 0) { |
| 1261 | ERROR5(NULL, NULL, NULL, |
| 1262 | "Incomplete expression '%s'.\n", ctxt->base); |
| 1263 | ctxt->error = 1; |
| 1264 | goto error; |
| 1265 | } |
| 1266 | } |
| 1267 | xmlCompileStepPattern(ctxt); |
| 1268 | if (ctxt->error != 0) |
| 1269 | goto error; |
| 1270 | SKIP_BLANKS; |
| 1271 | while (CUR == '/') { |
| 1272 | if (NXT(1) == '/') { |
no test coverage detected