knowledge(경쟁사): 모듈 46개 export 전수 — 계산 공용 라이브러리·동글·8차 해소

11번은 핵심 CPM 12개만 다뤘고 32개 모듈이 손대지 않은 채였음.

플러그인 규약
- 46개 중 31개 모듈이 Calc_Kanjub 를 내보냄. 재계산 진입점이 한 곳이 아니라
  모듈마다 있음. T8(UI 명령별 재계산 범위)이 어려운 까닭

DP_Common.CPM 73함수 = 계산 공용 라이브러리
- 식 평가 CALC_STR·CALC_STR_PART·CALC_STR_URC·GET_URC_TYP
- 중간변수 GET_VARI_VAL·SET_VARI_VAL (:=A01 라벨)
- 반올림 MROUNDUD·MROUNDUP·MTRUNC·MINT·MFRAC·GET_ROUND_CUT
- 조건 IIF·IFI·IFO·CHK_TRUE_CLSTR — 식에 조건 분기가 들어감
- AMTTOHAN 금액 한글 변환
- ⇒ 식 평가기는 사칙연산+ROUND 만으로 부족. 조건 함수와 중간변수 필요

ST_P_XLS.CPM 72함수 — 엑셀이 양방향 교환 경로
- CONV_XLS_2_ST(엑셀→STmate 역등록)·XLS_2_BDREC(엑셀→BDQTY)·Prn_FMLA_INFO
- 암호화된 BDQTY 를 엑셀에서 만들 수 있다는 뜻

SX32W.CPM 29함수 = Rainbow Sentinel SuperPro 동글 API
- 라이선스가 소프트키가 아니라 USB 동글. 통제시험이 영구 불가인 근거 확정

ST_Jabpum: Edt_Hal_Amt / Edt_Hal_Rate — 할증이 금액·율 두 갈래

변경 차수 8차 의문 해소
- PRJLST.SMT 섹션 최대 2, DBF 접미사 1~4, 바이너리에 1~3차변경만,
  BOQ2* 없음. 한 파일은 4벌이 맞고 8차는 분리형 파일 선택임

문서 24 신규, export 원자료와 스크립트 2개 추가.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Prk9BCHG1EMAywk9k8wegA
This commit is contained in:
2026-09-13 14:18:37 +09:00
co-authored by Claude Opus 5
parent 6bcc872851
commit 50113cb6f5
6 changed files with 296 additions and 1 deletions
@@ -30,6 +30,7 @@
| 21 정정과 트랙 통합 | **`SMT` 판정 정정 · 지식DB 트랙 셋 통합 · `PRJLST.SMT` 설정 원장 · 암호화의 성격** | (저장소 파일) |
| 22 UI 폼 분석 | **폼 233개 중 3개만 봤던 것** — 선택축 272개, `ACTTYP`·자리수 키·일괄변경 규칙 | (저장소 파일) |
| 23 `COSTN.SMT` 전수파싱 | **단가산출 원장** — 참조 1,570·품 1,460·Q식 187개(10꼴)·운반 사이클 | (저장소 파일) |
| 24 모듈구조 전수 | **46개 모듈 export**`DP_Common` 73함수, 플러그인 규약, 동글, 8차 해소 | (저장소 파일) |
> **정본은 저장소 파일이다** — `resources/knowledge/original/경쟁사 프로그램/STmate 분석/20_분석/`.
> 위 Orca 링크는 보기용이며, 문서를 지식DB 자리로 옮기면서 주소가 한 번 바뀌었다.
@@ -90,7 +91,13 @@
| `COSTN.SMT` 내용 | 「평문」까지만 | **전수 파싱** — 중기 참조 1,504건, 성분 셋을 각각 | 23번 |
| `Q` 식 | 한 꼴로 알았음 | ⚠ **최소 10가지 꼴** — 하드코딩 금지 | 23번 §3 |
| 운반 사이클 | 안 봤음 | **적재+왕복+적하** 구조·인자 확인 | 23번 §4 |
| 할증률 | `BDQTY` 암호화로 막힘 | ◐ **적용값 92건은 읽힘** | 23번 §5 |
| 할증률 | `BDQTY` 암호화로 막힘 | ◐ **적용값 92건은 읽힘**. 편집은 **금액·율 두 갈래** | 23번 §5, 24번 §5 |
| 모듈 분석 | 핵심 12개 | **46개 전수 export** | 24번 |
| 식 평가기 함수 | `CALC_STR` 만 | **A**`DP_Common` 73함수. 조건 `IIF`·중간변수·`MFRAC` 포함 | 24번 §2 |
| 재계산 진입점 | 한 곳으로 봄 | ⚠ **31개 모듈이 `Calc_Kanjub` 보유** | 24번 §1 |
| 라이선스 | 「없음」 | **Rainbow Sentinel SuperPro 하드웨어 동글** | 24번 §4 |
| 엑셀 | 단방향 출력 | **양방향**`CONV_XLS_2_ST`·`XLS_2_BDREC` | 24번 §3 |
| 변경 차수 8차 | ⚠ 미해결 | ✅ **해소** — 한 파일 4벌, 8차는 분리형 파일 선택 | 24번 §7 |
분석일: 2026-09-13
대상: `C:\경영정보(주)`
@@ -0,0 +1,121 @@
# 모듈 구조 전수 — 46개 모듈의 export 와 플러그인 규약
점검일: 2026-09-13
계기: 11번은 **핵심 CPM 12개**만 다뤘다. 나머지 **32개 모듈**이 손대지 않은 채였다.
재현 스크립트: `40_스크립트/module_export_sweep.py`
## 1. 플러그인 규약 — `Calc_Kanjub`
**46개 모듈 중 31개가 `Calc_Kanjub` 를 내보낸다.** 편집·인쇄·변환 무엇이든 **제비율 재계산을 스스로 부를 수 있는 공통 진입점**이다.
```text
Calc_Kanjub 31개 모듈이 공유
```
⇒ 「어느 화면에서 무엇을 고쳐도 제비율이 다시 돌 수 있다」는 뜻이다. 13번 **T8(UI 명령별 재계산 범위)**이 왜 어려운지가 여기서 보인다 — 재계산 진입점이 한 곳이 아니라 **모듈마다** 있다.
## 2. ⭐ `DP_Common.CPM` — 계산 공용 라이브러리 73함수
11번 §4.1은 `CALC_STR`만 언급했다. **실제 함수 집합 전체**는 이렇다.
### 2.1 식 평가
```text
CALC_STR 식 문자열 평가
CALC_STR_PART 부분 평가
CALC_STR_URC URC(자원참조) 포함 평가 ← &M00034M& 계열을 푸는 자리
GET_URC_TYP 참조 종류 판정
GET_VARI_VAL 변수 읽기 SET_VARI_VAL 변수 쓰기 ← :=A01 중간라벨
```
### 2.2 반올림·수치 — 11번 §4.2의 원 함수가 전부 여기 있다
```text
MROUNDUD 반올림 계열 MROUNDUP 올림 MTRUNC 절사
MINT 정수화 MFRAC 소수부
GET_ROUND_CUT 설정에 따라 위를 고르는 디스패처
MSTRTODBL · MSTRTOINT · ISNUM · ISINT · CH_FNTOVAL · FLOATTOSTR_ · EXTTOSTR
```
**`MFRAC`(소수부)가 새로 나왔다.** 18번 §2.2의 「`Q`를 소수 2자리로 먼저 확정」·17번 §2의 「성분 소계 절사」처럼 **소수부를 따로 다루는 자리**가 실제로 함수로 있다.
### 2.3 조건·논리
```text
IIF IFI IFO CHK_TRUE_CLSTR COUNT_LOGICAL
```
⇒ 식 문자열에 **조건 분기**가 들어간다. 11번 §4.1의 「선택 토큰(`[+LAB]`·`[+ANJ_B]`)을 옵션에 따라 포함/제거」가 이 함수들로 처리된다.
### 2.4 문자열·기타
`ADDBJVAL` · `ADDBSL` · `ADDSPSTR` · `CHANGE_STR` · `COPY_LEFT/RIGHT` · `LEFT_STR` · `RIGHT_STR` · `SEP_STR` · `REPLICA_STR` · `COUNT_STR` · `MPOS` · `NPOS` · `BPOS` · `DIS_FMT` · **`AMTTOHAN`**(금액 한글 변환 — 「금 일억삼천사백이십만원정」) · 파일 조작 20여 개.
**재구현 지침** — 식 평가기는 `+ - * /``ROUND` 계열만으로 부족하다. **`IIF`·`IFI`·`IFO` 조건 함수와 `GET_VARI_VAL`/`SET_VARI_VAL` 중간변수**까지 갖춰야 한다.
## 3. `ST_P_XLS.CPM` — XLSX 입출력 72함수
| 함수 | 뜻 |
|---|---|
| `MAKE_XLS` · `SHOW_XLS` · `FREE_XLS` | 엑셀 생성·표시·해제 |
| **`CONV_XLS_2_ST`** | **엑셀 → STmate 역등록** |
| **`XLS_2_BDREC`** | 엑셀 → `BDQTY` 레코드 |
| **`Prn_FMLA_INFO`** | **수식 정보 출력** — 출력 XLSX에 수식이 남는 까닭 |
| `MK_BSCBOQ_EXL` · `MK_EXL_BSCBOQ` | 기준 BOQ 양방향 |
| `Prn_*_EXL` 약 55개 | `SET_REP` 서식마다 엑셀판 |
⇒ **엑셀이 단순 출력이 아니라 양방향 교환 경로**다. `〓 INITIAL 〓` 시트(18번 §2.3)가 재등록 메타인 까닭이 `CONV_XLS_2_ST`에 있다.
**`XLS_2_BDREC`** — 암호화된 `BDQTY`**엑셀에서 만들 수 있다.** 뒤집으면 `BDQTY` 내용이 엑셀 수량산출 양식과 대응한다는 뜻이다.
## 4. `SX32W.CPM` — 라이선스는 하드웨어 동글
```text
RNBOsproInitialize · RNBOsproFindFirstUnit · RNBOsproQuery · RNBOsproRead
RNBOsproGetKeyInfo · RNBOsproGetSubLicense · RNBOsproSetDeveloperCode
RNBOsproCheckTerminalService · RNBOsproSetHeartBeat · RNBOsproReleaseLicense …29개
```
**Rainbow(현 Thales) Sentinel SuperPro** API다. `ST_BdSN.CPM``Chk_BD_SN`·`Chk_REG_SN`(시리얼 검사)이 함께 있다.
⇒ **라이선스가 소프트 키가 아니라 USB 동글**이다. 13번의 통제시험 T1~T11이 왜 「영구 불가」인지가 확정됐다 — 동글이 없으면 실행 자체가 안 된다.
## 5. 그 밖에 드러난 모듈
| 모듈 | export | 뜻 |
|---|---:|---|
| `ST_U_Archive.CPM` | 16 | **STC 압축·해제**`Chk_STC_Ver`(버전) · `ComP_Data` · `UnPack`/`UnPack1`/`UnPack_No` |
| `ST_P_Excav.CPM` | 15 | **굴착 전용 내역 양식**`Prn_Nae_Ex1_*` · `Ex2_*` 계열. 도로공사 양식 |
| `ST_P_Nae.CPM` | 30 | 내역·원가 인쇄 본진 |
| `ST_P_List.CPM` | 11 | 목록표 계열 |
| **`ST_Jabpum.CPM`** | 6 | **`Edt_Hal_Amt` vs `Edt_Hal_Rate`** — 할증을 **금액과 율 두 갈래**로 편집. 07번 §4의 「수량 할증 ≠ 금액 가산」이 export 이름에 그대로 |
| `ST_U_ADL.CPM` | 6 | 온라인 갱신 — `ST_Down_File` · `ST_UP_INFO_R` · `ST_SND_Mail` |
| `ST_Com_V.CPM` | 10 | `GET_*_R` 계열 — 모듈 간 자원 조회 규약 |
| `ST_Func_C.CPM` | 7 | `SUM_TOT` · `CON_TOT` · `ZERO_TOT` · `PCN_TO_T` · `OPTIMIZ`**계층 합산** |
| `CPMARC`/`CPMUNA` | 4+4 | ZIP 압축·해제 (Info-ZIP) |
| `STmexe.Cpm` | 2 | `Chk_Exe` · `Chk_New_Exe` — 자기 갱신 |
## 6. 이번 점검이 바꾸는 것
| 항목 | 이전 | 지금 |
|---|---|---|
| 모듈 분석 범위 | 핵심 12개 | **46개 전수 export** |
| 식 평가기 함수 집합 | `CALC_STR`만 알았음 | ✅ **73함수** — 조건(`IIF`)·중간변수·`MFRAC`까지 |
| 재계산 진입점 | 한 곳으로 봄 | ⚠ **31개 모듈이 `Calc_Kanjub` 보유** — T8이 어려운 까닭 |
| 라이선스 | 「없음」까지만 | ✅ **Rainbow Sentinel SuperPro 하드웨어 동글** |
| 엑셀 | 단방향 출력으로 봄 | ✅ **양방향**`CONV_XLS_2_ST` · `XLS_2_BDREC` |
| 할증 | 한 갈래로 봄 | ✅ **금액·율 두 갈래** (`Edt_Hal_Amt`/`Edt_Hal_Rate`) |
| 변경 차수 8차 의문 | 미해결 | ✅ **해소** — 아래 |
## 7. 변경 차수 8차 의문 해소
22번 §3.3에서 「화면은 8차인데 `COSTN` 접미사는 4벌」이라 남겨 둔 것을 확인했다.
| 근거 | 결과 |
|---|---|
| `PRJLST.SMT` 차수 섹션 | 표본 7건 모두 **최대 `[1_KANJUB]`·`[2_KANJUB]`** |
| DBF 접미사 | `PRJLST`·`BOQ11`·`COSTN` 모두 **1~4 네 벌** |
| 바이너리 문자열 | **`1차변경`~`3차변경`만** 존재. 4~8차 없음 |
| `BOQ1*` / `BOQ2*` | `BOQ1` 15개 모듈, **`BOQ2`는 0개** |
**한 파일이 담는 것은 4벌(원설계 + 3차변경)이 맞다.** 화면의 1~8차는 **분리형으로 파일을 이어 갔을 때 그 파일들을 고르는 인쇄 선택**이다(16번 §4.6의 차수 인계). 저장 구조 의문은 없다.
@@ -0,0 +1,61 @@
### CPM/EXE export 전수 — 모듈 44개, export 408개(중복포함)
11번이 다룬 핵심 12개 말고 **32개 모듈**이 남아 있었음
CPMARC.CPM 4개 GetZipDllPrivVersion, GetZipDllVersion, ZipDllExec, ___CPPdebugHook
CPMUNA.CPM 4개 GetUnzDllPrivVersion, GetUnzDllVersion, UnzDllExec, ___CPPdebugHook
DP_Common.CPM 73개 ADDBJVAL, ADDBSL, ADDSPSTR, AMTTOHAN, BPOS, CALC_STR, CALC_STR_PART, CALC_STR_URC, CHANGE_STR, C
DP_MinMsg.CPM 3개 GETNEWCODE_NAME, GETSPCHAR, MINIMSG
ST_BdSN.CPM 3개 Chk_BD_SN, Chk_BD_USE, Chk_REG_SN
✅ ST_Boq.CPM 4개 Add_From_MRG, Calc_Kanjub, Edit_Boq, Edit_Bqm
ST_Com_V.CPM 10개 GET_CAL_R, GET_COM_R, GET_IMS_R, GET_MRG_R, GET_PBL_R, GET_PRN_R, GET_SFC_R, GET_STM_R, GET_SYS_
ST_EdSan.CPM 3개 Calc_Kanjub, Edit_EQ_SYNC, Edit_SanKun
✅ ST_EdiLWi.CPM 2개 Calc_Kanjub, Edit_iLW
ST_FindUse.CPM 3개 Calc_Kanjub, Find_BDQ, Find_BOQ
ST_Func_C.CPM 7개 CON_TOT, OPTIMIZ, PCN_TO_T, SUM_TOT, VALTOPOS, ZERO_TO, ZERO_TOT
ST_Jabpum.CPM 6개 Calc_Kanjub, Edit_Dan, Edit_Strg, Edt_Hal_Amt, Edt_Hal_Rate, View_JabPum
✅ ST_KanJub.CPM 5개 Calc_Kanjub, Edit_KanJub, Edit_KanJub_K, Edit_Kan_Rate, Prn_Kan_Rate
ST_Merge_Code.CPM 1개 Calc_Kanjub
ST_PList.CPM 3개 Calc_Kanjub, Call_MRG, Call_PLIST
✅ ST_P_Collect.CPM 5개 Calc_Kanjub, Prn_Col_Dan, Prn_Col_Dan_L, Prn_Col_X, Prn_Col_X_L
✅ ST_P_ConEst.CPM 9개 Calc_Kanjub, Prn_Jab_K, Prn_Nae_C1, Prn_Nae_C2, Prn_Nae_C3, Prn_Nae_Est, Prn_Nae_K1, Prn_Nae_K2,
ST_P_Excav.CPM 15개 Calc_Kanjub, Prn_Nae_Ex1_0, Prn_Nae_Ex1_1, Prn_Nae_Ex1_2, Prn_Nae_Ex1_C1, Prn_Nae_Ex1_C2, Prn_Na
✅ ST_P_Joong.CPM 7개 Calc_Kanjub, Prn_Joong, Prn_Joong2, Prn_Joong2_L, Prn_Joong_C, Prn_Joong_C_L, Prn_Joong_L
ST_P_List.CPM 11개 Calc_Kanjub, Prn_AList, Prn_Comp_M, Prn_Comp_M1, Prn_Comp_M1_L, Prn_Dan, Prn_Dan_L, Prn_SanMok,
ST_P_Nae.CPM 30개 Calc_Kanjub, Prn_Boq_Not, Prn_Bqm, Prn_Jab, Prn_Jab_P, Prn_Nae, Prn_NaeW, Prn_NaeW_P, Prn_Nae_B,
ST_P_San.CPM 3개 Calc_Kanjub, Prn_San_L, Prn_San_P
ST_P_XLS.CPM 72개 CONV_XLS_2_ST, Calc_Kanjub, Chk_Xls_File, FIND_PRT_INDX, FREE_XLS, MAKE_XLS, MK_BSCBOQ_EXL, MK_E
ST_P_iLWi.CPM 3개 Calc_Kanjub, Prn_iLWi, Prn_iLWi_S
ST_Prt.CPM 4개 Calc_Kanjub, GS_Prn_Rec, Prn_Prt, Rep_Print
✅ ST_SanCal.CPM 2개 Calc_Kanjub, Calq_San
ST_Sys.CPM 2개 Calc_Kanjub, Set_Sys_1
ST_U_ADL.CPM 6개 Get_Real_Time, ST_Down_File, ST_NEW_INFO, ST_SND_Mail, ST_UP_DNINFO, ST_UP_INFO_R
ST_U_Archive.CPM 16개 Calc_Kanjub, Chk_ArcName, Chk_Data, Chk_STC_Ver, Chk_STDir, ComP_CurBOQ, ComP_Data, ComP_FOLD, C
✅ ST_U_ChgAmt.CPM 2개 CHANGE_AMT, Calc_Kanjub
✅ ST_U_ChgCode.CPM 10개 Calc_Kanjub, Chg_Code_All, Chg_Code_Plus, Chg_Code_Sel, Chk_Chg_Code_1, Chk_True_Rep_Code, Exec_
✅ ST_U_ConBD.CPM 4개 CONBD_USD_QTY, CON_QTY, CON_QTY9, Calc_Kanjub
✅ ST_U_Convert.CPM 20개 Appn_Tag_REP, CHK_K_FLD, Calc_Kanjub, Conv_BOQ, Conv_Equip, Conv_Jodal_ST8, Conv_ST8_Jodal, Conv
ST_U_DelCode.CPM 6개 Calc_Kanjub, Chk_True_Del_1, Del_Code_A_T, Del_Code_A_X, Del_Code_Sel, Exec_Delete_Code
ST_U_DelPrj.CPM 3개 Calc_Kanjub, Delete_Prj, Merge_Prj
ST_U_Indx.CPM 2개 Calc_Kanjub, INDX_ALL
ST_U_Merge.CPM 2개 Calc_Kanjub, ST_MERGE
ST_VSetup.EXE 2개 _MainWndProc@16, _StubFileWrite@12
STmate.Cpm 1개 Calc_Kanjub
✅ STmateQty8.CPM 4개 Calc_Kanjub, FIND_QCODE, Free_Qty, ST_QTY
STmexe.Cpm 2개 Chk_Exe, Chk_New_Exe
SX32W.CPM 29개 RNBOsproActivate, RNBOsproCheckTerminalService, RNBOsproCleanup, RNBOsproDecrement, RNBOsproEnum
UNWISE.EXE 4개 _ItemDlg@16, _MainWndProc@16, _PromptDlg@16, _SharedDlg@16
View_Old_San.CPM 1개 Show_Old_San
### 여러 모듈이 공유하는 export (플러그인 공통 규약)
Calc_Kanjub 31개 모듈
___CPPdebugHook 2개 모듈
Prn_Boq_Not 2개 모듈
Prn_Nae_ColL 2개 모듈
Prn_Nae_ColM 2개 모듈
Prn_Nae_ColX 2개 모듈
Prn_Nae_Cont1 2개 모듈
Prn_Nae_Cont2 2개 모듈
_MainWndProc@16 2개 모듈
GetZipDllPrivVersion 1개 모듈
GetZipDllVersion 1개 모듈
ZipDllExec 1개 모듈
@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
"""CPM 46개 모듈의 export 함수 전수 — 11번은 핵심 12개만 했음."""
import sys, io, pathlib, struct, collections, re
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")
ROOT = pathlib.Path(r"C:\경영정보(주)\System")
def exports(b):
try:
e=struct.unpack_from("<I",b,0x3C)[0]
if b[e:e+4]!=b"PE\0\0": return []
nsec=struct.unpack_from("<H",b,e+6)[0]; optsz=struct.unpack_from("<H",b,e+20)[0]
opt=e+24; magic=struct.unpack_from("<H",b,opt)[0]
dd=opt+(96 if magic==0x10b else 112)
erva,esz=struct.unpack_from("<II",b,dd)
if not erva: return []
secs=[]; so=opt+optsz
for i in range(nsec):
s=b[so+i*40:so+i*40+40]
vsz,va,rsz,ptr=struct.unpack_from("<IIII",s,8); secs.append((va,vsz,ptr,rsz))
def r2o(r):
for va,vsz,ptr,rsz in secs:
if va<=r<va+max(vsz,rsz): return ptr+(r-va)
eo=r2o(erva)
if eo is None: return []
nnames=struct.unpack_from("<I",b,eo+24)[0]
namp=struct.unpack_from("<I",b,eo+32)[0]
no=r2o(namp)
out=[]
for i in range(min(nnames,4000)):
nr=struct.unpack_from("<I",b,no+4*i)[0]
o=r2o(nr)
if o is None: continue
end=b.index(b"\0",o)
out.append(b[o:end].decode("latin1"))
return out
except Exception: return []
per={}; allx=collections.Counter()
for p in sorted(ROOT.rglob("*")):
if not p.is_file() or p.suffix.upper() not in (".CPM",".EXE"): continue
try: b=p.read_bytes()
except Exception: continue
if b[:2]!=b"MZ": continue
x=exports(b)
if x: per[p.name]=sorted(x)
for n in x: allx[n]+=1
DONE={"ST_Boq.CPM","ST_EdiLWi.CPM","ST_KanJub.CPM","ST_SanCal.CPM","STmateQty8.CPM","ST_P_Joong.CPM",
"ST_P_Collect.CPM","ST_P_ConEst.CPM","ST_U_ChgAmt.CPM","ST_U_ChgCode.CPM","ST_U_ConBD.CPM","ST_U_Convert.CPM"}
print("### CPM/EXE export 전수 — 모듈 %d개, export %d개(중복포함)" % (len(per), sum(len(v) for v in per.values())))
print(" 11번이 다룬 핵심 12개 말고 **%d개 모듈**이 남아 있었음\n" % len([k for k in per if k not in DONE]))
for nm,x in sorted(per.items()):
mark = "" if nm in DONE else " "
print("%s %-22s %2d%s" % (mark, nm[:22], len(x), ", ".join(x)[:96]))
print("\n### 여러 모듈이 공유하는 export (플러그인 공통 규약)")
for n,c in allx.most_common(12): print(" %-22s %2d개 모듈" % (n,c))
@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
"""변경 차수 저장 구조 — DBF 슬롯 4벌 vs 화면 8차의 어긋남을 가른다."""
import sys, io, re, pathlib, zipfile, struct, collections
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")
ROOT = pathlib.Path(r"D:\aislo-wt\sub\resources\knowledge\original\실무문서")
def fields(b):
f=[];o=32
while b[o]!=0x0D: f.append(b[o:o+11].rstrip(b"\0").decode("cp949","replace")); o+=32
return f
print("### ① PRJLST.SMT 의 차수 섹션")
for p in sorted(ROOT.rglob("*.STC")):
try: z=zipfile.ZipFile(p); b=z.read("PRJLST.SMT")
except Exception: continue
secs=sorted({s for s in re.findall(r"\[([0-9]+)_KANJUB\]",
"".join(ch for ch in b[0x200:].decode("cp949","replace")))}, key=int)
print(" %-46s 섹션 %s" % (p.stem[:46], secs or "없음"))
print("\n### ② DBF 의 차수 슬롯 (접미사 숫자)")
for p in list(sorted(ROOT.rglob("*.STC")))[:2]:
z=zipfile.ZipFile(p)
print("\n-- %s" % p.stem[:50])
for t in ("PRJLST.DBF","BOQ11.DBF","COSTN.DBF"):
try: f=fields(z.read(t))
except Exception: continue
sfx=collections.Counter()
for n in f:
m=re.search(r"(\d)$", n)
if m: sfx[m.group(1)]+=1
print(" %-12s 필드 %3d개 접미사별: %s" % (t, len(f), dict(sorted(sfx.items()))))
print("\n### ③ 화면·코드가 말하는 차수 상한")
SYS=pathlib.Path(r"C:\경영정보(주)\System")
pat=[rb"[1-9]\xec\xb0\xa8\xeb\xb3\x80\xea\xb2\xbd"] # UTF-8 'n차변경' — cp949 로 다시
import re as _re
need=[("%d차변경"%i).encode("cp949") for i in range(1,10)]
hit=collections.Counter()
for p in SYS.rglob("*"):
if not p.is_file(): continue
try: b=p.read_bytes()
except Exception: continue
if b[:2]!=b"MZ": continue
for i,n in enumerate(need,1):
if n in b: hit[i]+=1
print(" 'n차변경' 문자열을 가진 모듈 수: %s" % dict(sorted(hit.items())))
for tok in (b"BOQ1", b"BOQ2"):
c=sum(1 for p in SYS.rglob("*") if p.is_file() and p.suffix.upper()==".CPM" and tok in p.read_bytes())
print(" '%s' 를 가진 CPM 모듈 %d" % (tok.decode(), c))
@@ -62,6 +62,7 @@
| 21 | **정정과 트랙 통합**`SMT` 정정, 지식DB 세 트랙, 암호화의 성격 |
| 22 | **UI 폼 분석** — 선택축 272개, 화면에 남아 있던 계산 규칙 |
| 23 | **`COSTN.SMT` 전수파싱** — 단가산출 원장, Q식 10꼴, 운반 사이클 |
| 24 | **모듈구조 전수** — 46개 export, 계산 공용 라이브러리 73함수, 동글 |
## 확정된 굵직한 것