1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
/*
* COPYRIGHT
*
* pcb-rnd, interactive printed circuit board design
* Copyright (C) 2016,2020,2024 Tibor 'Igor2' Palinkas
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Contact:
* Project page: http://repo.hu/projects/pcb-rnd
* lead developer: http://repo.hu/projects/pcb-rnd/contact.html
* mailing list: pcb-rnd (at) list.repo.hu (send "subscribe")
*/
/* Query language - execution */
#ifndef PCB_QUERY_EXEC_H
#define PCB_QUERY_EXEC_H
#include "query.h"
#include <genht/htpp.h>
#include <genht/htpi.h>
#include <time.h>
#define PCB_QRY_MAX_FUNC_ARGS 64
struct pcb_qry_exec_s {
pcb_board_t *pcb;
pcb_qry_node_t *root;
pcb_qry_val_t all; /* a list of all objects */
pcb_query_iter_t *iter; /* current iterator */
vtp0_t autofree;
unsigned cfg_prefer_term:1; /* prefer ending in terminal */
int (*progress_cb)(pcb_qry_exec_t *ec, long at, long total);
void *progress_ctx;
/* data/call cache */
htpp_t obj2netterm; /* (pcb_any_obj_t *) object -> (pcb_any_obj_t *) terminal with the lowest ID on the net segment; for floating segments any object with the lowest ID will be accepted */
htpp_t obj2lenseg; /* (pcb_any_obj_t *) object -> (pcb_any_obj_t *) length-segment head: each length-segment is a junction-free part of the network */
htpi_t obj2lenseg_cc; /* (pcb_any_obj_t *) object -> connection-counter (how many different objects are connected) */
vtp0_t obj2lenseg_free; /* delayed free of obj2lenseg_cc objects */
vtp0_t tmplst; /* may be reused in a function call to save on allocation; always clear it at the end of the fnc */
htpp_t layer_setup_precomp; /* fnc layer_setup(): cache precompiled conditions */
vtp0_t layer_setup_netobjs; /* fnc layer_setup(): tmp allocation cache for object listing */
void *layer_setup_res_cache; /* fnc layer_setup(): cached results for each condition evaluated - requests tend to repeat */
time_t last_prog_cb;
void *layer_ko_match; /* fnc layer_ko_match(); key is a fake pointer build of two layer group indices */
unsigned obj2netterm_inited:1;
unsigned obj2lenseg_inited:1;
unsigned layer_setup_inited:1;
unsigned layer_ko_match_inited:1;
unsigned warned_missing_thickness:1;
unsigned trace:1;
};
/* if bufno is -1, scope is the board, else scope is the buffer addressed by bufno */
void pcb_qry_init(pcb_qry_exec_t *ctx, pcb_board_t *pcb, pcb_qry_node_t *root, int bufno);
void pcb_qry_uninit(pcb_qry_exec_t *ctx);
/* parts of init/uninit for the case a single pcb_qry_exec_t is used for
multiple queries for sharing the cache */
void pcb_qry_setup(pcb_qry_exec_t *ctx, pcb_board_t *pcb, pcb_qry_node_t *root);
void pcb_qry_autofree(pcb_qry_exec_t *ctx);
/* Execute an expression or a rule; if ec is NULL, use a temporary context and
free it before returning; else ec is the shared context for multiple queries
with persistent cache */
int pcb_qry_run(pcb_qry_exec_t *ec, pcb_board_t *pcb, pcb_qry_node_t *prg, int bufno, void (*cb)(void *user_ctx, pcb_qry_val_t *res, pcb_any_obj_t *current), void *user_ctx);
int pcb_qry_is_true(pcb_qry_val_t *val);
int pcb_qry_eval(pcb_qry_exec_t *ctx, pcb_qry_node_t *node, pcb_qry_val_t *res, void (*cb)(void *user_ctx, pcb_qry_val_t *res, pcb_any_obj_t *current), void *user_ctx);
int pcb_qry_it_reset(pcb_qry_exec_t *ctx, pcb_qry_node_t *node);
int pcb_qry_it_reset_(pcb_qry_exec_t *ctx, int persistent);
/* Returns 1 if context iterator is valid, 0 if the loop is over */
int pcb_qry_it_next(pcb_qry_exec_t *ctx);
void pcb_qry_val_free_fields(pcb_qry_val_t *val);
/* Helper macros: load value o and return 0 */
#define PCB_QRY_RET_INT_SRC(o, value, node) \
do { \
o->source = node; \
o->type = PCBQ_VT_LONG; \
o->data.lng = value; \
return 0; \
} while(0)
#define PCB_QRY_RET_INT(o, value) PCB_QRY_RET_INT_SRC(o, value, NULL)
#define PCB_QRY_RET_OBJ_SRC(o, value, node) \
do { \
o->source = node; \
o->type = PCBQ_VT_OBJ; \
o->data.obj = value; \
return 0; \
} while(0)
#define PCB_QRY_RET_OBJ(o, value) PCB_QRY_RET_OBJ_SRC(o, value, NULL)
#define PCB_QRY_RET_DBL_SRC(o, value, node) \
do { \
o->source = node; \
o->type = PCBQ_VT_DOUBLE; \
o->data.dbl = value; \
return 0; \
} while(0)
#define PCB_QRY_RET_DBL(o, value) PCB_QRY_RET_DBL_SRC(o, value, NULL)
#define PCB_QRY_RET_COORD_SRC(o, value, node) \
do { \
o->source = node; \
o->type = PCBQ_VT_COORD; \
o->data.crd = value; \
return 0; \
} while(0)
#define PCB_QRY_RET_COORD(o, value) PCB_QRY_RET_COORD_SRC(o, value, NULL)
#define PCB_QRY_RET_STR_SRC(o, value, node) \
do { \
o->source = node; \
o->type = PCBQ_VT_STRING; \
o->data.str = value; \
return 0; \
} while(0)
#define PCB_QRY_RET_STR(o, value) PCB_QRY_RET_STR_SRC(o, value, NULL)
#define PCB_QRY_RET_SIDE_SRC(o, on_bottom, node) \
do { \
o->source = node; \
o->type = PCBQ_VT_STRING; \
o->data.str = on_bottom ? "BOTTOM" : "TOP"; \
return 0; \
} while(0)
#define PCB_QRY_RET_SIDE(o, value) PCB_QRY_RET_SIDE_SRC(o, value, NULL)
/* The case when the operation couldn't be carried out, sort of NaN */
#define PCB_QRY_RET_INV_SRC(o, node) \
do { \
o->source = node; \
o->type = PCBQ_VT_VOID; \
return 0; \
} while(0)
#define PCB_QRY_RET_INV(o) PCB_QRY_RET_INV_SRC(o, NULL)
/* Convert src_arg to coordinate and cache the result if src_arg is tied
to a tree node */
#define PCB_QRY_ARG_CONV_TO_COORD(dst_crd, src_arg, err_inst) \
do { \
rnd_bool succ; \
if ((src_arg)->type == PCBQ_VT_COORD) { dst_crd = (src_arg)->data.crd; break; } \
if ((src_arg)->type == PCBQ_VT_LONG) { dst_crd = (src_arg)->data.lng; break; } \
if ((src_arg)->type == PCBQ_VT_DOUBLE) { dst_crd = rnd_round((src_arg)->data.dbl); break; } \
if ((src_arg)->type == PCBQ_VT_STRING) { \
dst_crd = rnd_get_value((src_arg)->data.str, NULL, NULL, &succ); \
if (succ) break; \
} \
err_inst; \
} while(0)
#endif
|