Приоритетность загрузки lisp
Можно сказать, продолжение О кодах, загрузке и компиляции и О кодах, загрузке и компиляции, часть 2. Пишу здесь, чтобы самому не потерять информацию. А то с меня станется...
Итак: столкнулся я тут с интересной задачкой - имеет ли значение последовательность "прописывания" lisp-кодов в файл-исходник для fas?
Блин, оказалось, имеет. Особенно если в коде есть самовызываемые функции.
При этом fas может вполне нормально скомпилироваться, например, в 2002, но не работать в 2005..2006 (возможно, еще и в 2007 - пока проверить нет возможности). Но этот же fas прекрасно будет себя чувствовать в 2002, 2004, 2008 и дальше. Магия? Или Autodesk немного похимичила?
Как бы то ни было, побороть это нельзя, придется "обходить".
В качестве первой прикидки написал нечто такого типа:
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 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 | (defun _kpblc-load-priority (path mask / fun_conv-value-to-string fun_conv-list-to-string fun_eval-value-round fun_list-dublicates-remove fun_list-add-or-subst fun_browsefiles-in-directory-nested fun_conv-string-to-list fun_eval-prior file_lst err_lst ) ;| * Вычисляет последовательность загрузки lsp-кодов * Параметры вызова: path каталог расположения исходных кодов. Оттуда "проверяются" все файлы lsp mask маска вызова функций * Примеры вызова: (kpblc:load-priority "b:\\_отчуждаемые\\semantic" "*kpblc*") |; (defun fun_list-add-or-subst (lst key value) ;| * Производит замену или дополнение элемента списка новым * Параметры вызова: lst обрабатываемый список key ключ value устанавливаемое значение |; (if (not value) (vl-remove-if (function (lambda (x) (= (car x) key))) lst) (if (cdr (assoc key lst)) (subst (cons key value) (assoc key lst) lst) (cons (cons key value) lst) ) ;_ end of if ) ;_ end of if ) ;_ end of defun (defun fun_list-dublicates-remove (lst / result) ;| * Функция исключения дубликатов элементов списка * Параметры вызова: * lst обрабатываемый список * Возвращаемое значение: список без дубликатов соседних элементов * Примеры вызова: (fun_list-dublicates-remove '((0.0 0.0 0.0) (10.0 0.0 0.0) (10.0 0.0 0.0) (0.0 0.0 0.0)) nil) ((0.0 0.0 0.0) (10.0 0.0 0.0) (0.0 0.0 0.0)) |; (foreach x lst (if (not (member x result)) (setq result (cons x result)) ) ;_ end of if ) ;_ end of foreach (reverse result) ) ;_ end of defun (defun fun_eval-value-round (value to) ;| ;; http://forum.dwg.ru/showthread.php?p=301275 * Выполняет округление числа до указанной точности * Примеры вызова: (fun_eval-value-round 16.365 0.01) ; 16.37 |; (if (zerop to) value (* (atoi (rtos (/ (float value) to) 2 0)) to) ) ;_ end of if ) ;_ end of defun (defun fun_conv-value-to-string (value /) ;| * конвертация значения в строку. |; (cond ((= (type value) 'str) value) ((= (type value) 'int) (itoa value)) ((and (= (type value) 'real) (equal value (fun_eval-value-round value 1.) 1e-6)) (itoa (fix value)) ) ((= (type value) 'real) (rtos value 2 14)) ((not value) "") (t (vl-princ-to-string value)) ) ;_ end of cond ) ;_ end of defun (defun fun_conv-list-to-string (lst sep) ;| * Преобразование списка в строку * Параметры вызова: lst обрабатываемй список sep разделитель. nil -> " " |; (if (and lst (setq lst (mapcar (function fun_conv-value-to-string) lst)) (setq sep (if sep sep " " ) ;_ end of if ) ;_ end of setq ) ;_ end of and (strcat (car lst) (apply (function strcat) (mapcar (function (lambda (x) (strcat sep x) ) ;_ end of lambda ) ;_ end of function (cdr lst) ) ;_ end of mapcar ) ;_ end of apply ) ;_ end of strcat "" ) ;_ end of if ) ;_ end of defun (defun fun_conv-string-to-list (string separator / i) ;| * Функция разбора строки. Возвращает список либо точечную пару. * Параметры вызова: * string разбираемая строка * separator символ, используемый в качестве разделителя частей * Примеры вызова: (fun_conv-string-to-list "1;2;3;4;5;6" ";") ;'(1 2 3 4 5 6) (fun_conv-string-to-list "1;2" ";") ;'(1 2) * За основу взяты уроки Евгения Елпанова по рекурсиям |; (cond ((= string "") nil) ((vl-string-search separator string) ((lambda (/ pos res) (while (setq pos (vl-string-search separator string)) (setq res (cons (substr string 1 pos) res) string (substr string (+ (strlen separator) 1 pos)) ) ;_ end of setq ) ;_ end of while (reverse (cons string res)) ) ;_ end of lambda ) ) (t (list string)) ) ;_ end of cond ) ;_ end of defun (defun fun_browsefiles-in-directory-nested (path mask) ;;; Функция возвращает список файлов указанной маски, находящихся в ;;; заданном каталоге ;;; Параметры вызова: ;;; path путь к корневому каталогу. nil недопустим ;;; mask маска имени файла. nil или список недопустим ;;; Примеры вызова: ;| (fun_browsefiles-in-directory-nested "c:\\documents" "*.dwg") |; (apply (function append) (cons (if (vl-directory-files path mask) (mapcar (function (lambda (x) (strcat (vl-string-right-trim "\" path) "\" x)) ;_ end of lambda ) ;_ end of function (vl-directory-files path mask) ) ;_ end of mapcar ) ;_ if (mapcar (function (lambda (x) (fun_browsefiles-in-directory-nested (strcat (vl-string-right-trim "\" path) "\" x) mask) ) ;_ end of lambda ) ;_ end of function (vl-remove ".." (vl-remove "." (vl-directory-files path nil -1))) ;_ end of vl-remove ) ;_ mapcar ) ;_ cons ) ;_ end of apply ) ;_ end of defun (defun fun_eval-prior (item / res) ;| * вычисление приоритета загрузки * Параметры вызова: item элемент file_lst '(("file" . "B:\\_отчуждаемые\\semantic\\kpblc-semantic-loader.LSP") ("calls" "kpblc-semantic-loader" "fun_autoload-autostart") ("defuns" "kpblc-semantic-loader") ("prior")) lst file_lst |; ;; (princ (strcat "\n File : " (cdr(assoc"file"item)))) (cond ((setq res (cdr (assoc "prior" item)))) (t (setq res (apply (function +) (mapcar (function (lambda (calls) (+ 1. ((lambda (/ tmp) (setq tmp (car (vl-remove-if-not (function (lambda (x) (member (strcase calls) (mapcar (function strcase) (cdr (assoc "defuns" x)))) ) ;_ end of lambda ) ;_ end of function file_lst ) ;_ end of vl-remove-if-not ) ;_ end of car ) ;_ end of setq (if (not tmp) (progn (if (not (member (strcase (vl-filename-base (cdr (assoc "file" item))) t) (mapcar (function car) err_lst ) ;_ end of mapcar ) ;_ end of member ) ;_ end of not (setq err_lst (cons (cons (strcase (vl-filename-base (cdr (assoc "file" item))) t) (if (listp calls) (fun_conv-list-to-string calls "; ") calls ) ;_ end of if ) ;_ end of cons err_lst ) ;_ end of cons ) ;_ end of setq ) ;_ end of if 0 ) ;_ end of progn (fun_eval-prior tmp) ) ;_ end of if ) ;_ end of lambda ) ;; file_lst ;; ) ;_ end of fun_eval-prior ) ;_ end of + ) ;_ end of lambda ) ;_ end of function (cdr (assoc "calls" item) ) ;_ end of cdr ) ;_ end of mapcar ) ;_ end of apply file_lst (subst (subst (cons "prior" res) (assoc "prior" item) item) item file_lst ) ;_ end of subst ;; (fun_list-add-or-subst file_lst item (subst (cons "prior" res ) (assoc"prior"item) item)) ) ;_ end of setq ) ) ;_ end of cond ;(princ (strcat "\n File : " (vl-filename-base (cdr (assoc "file" item))) " prior : " (rtos res 2 0)) ; ) ;_ end of princ res ) ;_ end of defun (setq file_lst (mapcar (function (lambda (file / handle str calls defuns is_comment) (setq handle (open file "r")) (while (setq str (read-line handle)) (setq str (vl-string-trim " \t" str)) (if (wcmatch str "*;|,;*") (setq is_comment t str (fun_conv-list-to-string (cdr (fun_conv-string-to-list str ";|")) " ") ) ;_ end of setq ) ;_ end of if (if (wcmatch str "*|;*") (setq is_comment nil str (fun_conv-list-to-string (cdr (fun_conv-string-to-list str "|;")) " ") ) ;_ end of setq ) ;_ end of if (if (not is_comment) (cond ((wcmatch (strcase str) (strcat "*(DEFUN " (strcase mask) "*")) (setq defuns (cons str defuns)) ) ((and (wcmatch (strcase str) (strcat "*(" (strcase mask) "*")) (not (wcmatch (strcase str) (strcat "*`*" (strcase mask) "*"))) ) ;_ end of and (setq calls (cons (vl-string-trim " \t" str) calls)) ) ) ;_ end of cond ) ;_ end of cond ) ;_ end of while (close handle) (list (cons "file" (findfile file)) (cons "calls" (fun_list-dublicates-remove (vl-remove-if (function (lambda (x) (wcmatch x ""*,*"") ) ;_ end of lambda ) ;_ end of function (mapcar (function (lambda (x) (vl-string-trim " ()'" x) ) ;_ end of lambda ) ;_ end of function (vl-remove-if-not (function (lambda (x) (wcmatch (strcase x) (strcase mask)) ) ;_ end of lambda ) ;_ end of function (apply (function append) (mapcar (function (lambda (x) (fun_conv-string-to-list x " ") ) ;_ end of lambda ) ;_ end of function calls ) ;_ end of mapcar ) ;_ end of apply ) ;_ end of vl-remove-if-not ) ;_ end of mapcar ) ;_ end of vl-remove-if ) ;_ end of fun_list-dublicates-remove ) ;_ end of cons (cons "defuns" (mapcar (function (lambda (x) (vl-string-trim " ()" x) ) ;_ end of lambda ) ;_ end of function (vl-remove-if-not (function (lambda (x) (wcmatch (strcase x) (strcase mask)) ) ;_ end of lambda ) ;_ end of function (apply (function append) (mapcar (function (lambda (x) (fun_conv-string-to-list x " ") ) ;_ end of lambda ) ;_ end of function defuns ) ;_ end of mapcar ) ;_ end of apply ) ;_ end of vl-remove-if-not ) ;_ end of mapcar ) ;_ end of cons (cons "prior" (if (= (length calls) 0) -1 ) ;_ end of if ) ;_ end of cons ) ;_ end of list ) ;_ end of lambda ) ;_ end of function (vl-remove-if (function (lambda (x) (vl-catch-all-error-p (vl-catch-all-apply (function (lambda () (load x) ) ;_ end of lambda ) ;_ end of function ) ;_ end of vl-catch-all-apply ) ;_ end of vl-catch-all-error-p ) ;_ end of lambda ) ;_ end of function (fun_browsefiles-in-directory-nested path "*.lsp") ) ;_ end of vl-remove-if ) ;_ end of mapcar file_lst (mapcar (function (lambda (x) (fun_list-add-or-subst x "calls" (vl-remove-if (function (lambda (x1) (member (strcase x1) (mapcar (function strcase) (cdr (assoc "defuns" x)))) ) ;_ end of lambda ) ;_ end of function (cdr (assoc "calls" x)) ) ;_ end of vl-remove-if ) ;_ end of fun_list-add-or-subst ) ;_ end of lambda ) ;_ end of function file_lst ) ;_ end of mapcar ) ;_ end of setq (mapcar (function (lambda (x) (fun_eval-prior x) ) ;_ end of lambda ) ;_ end of function (vl-remove nil file_lst) ) ;_ end of mapcar (if err_lst ((lambda (/ filelog handle) (setq filelog (strcat (vl-string-right-trim "\" path) "\\eval.log") handle (open filelog "w") ) ;_ end of setq (mapcar (function (lambda (err) (write-line (strcat "File " (car err) " uses : " (cdr err)) handle) ) ;_ end of lambda ) ;_ end of function (vl-sort err_lst '(lambda (a b) (< (car a) (car b)))) ) ;_ end of mapcar (close handle) ) ;_ end of lambda ) ) ;_ end of if (vl-sort file_lst (function (lambda (a b) (< (cdr (assoc "prior" a)) (cdr (assoc "prior" b)))))) ) ;_ end of defun |
Исходник болтается здесь.
Пример использования не прописываю подробно, но некоторые вешки хотелось бы сделать:
- "Сольем" все в единый lsp-файл
- Определяем имя этого файла, открываем его для записи
- Копируем в него каждый файл из _kpblc-load-priority
- Закрываем хендл файла
- Создаем проект и компилируем его