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
|
page 80,132
; SCCSID = @(#)tprintf.asm 4.3 85/07/02
; SCCSID = @(#)tprintf.asm 4.3 85/07/02
TITLE COMMAND Transient Printf routine
;****************************************************************
;*
;* ROUTINE: STD_PRINTF/STD_EPRINTF
;*
;* FUNCTION: Set up to print out a message using SYSDISPMSG.
;* Set up substitutions if utility message. Make
;* sure any changes to message variables in TDATA
;* are reset to avoid reloading the transient.
;*
;* INPUT: Msg_Disp_Class - set to message class
;* Msg_Cont_Flag - set to control flags
;* DS points to transient segment
;*
;* if utility message:
;* DX points to a block with message number
;* (word), number of substitutions (byte),
;* followed by substitution list if there
;* are substitutions. If substitutions
;* are not in transient segment they must
;* be set.
;* else
;* AX set to message number
;*
;* OUTPUT: none
;*
;****************************************************************
.xlist
.xcref
INCLUDE comsw.asm ;AC000;
INCLUDE DOSSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm ;AN000;
INCLUDE SYSMSG.INC ;AN000;
.list
.cref
datares segment public
extrn pipeflag:byte
datares ends
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN extend_buf_off:word ;AN000;
EXTRN Extend_Buf_ptr:word ;AN000;
EXTRN Extend_Buf_seg:word ;AN000;
EXTRN Msg_Cont_Flag:byte ;AN000;
EXTRN Msg_disp_Class:byte ;AN000;
EXTRN pipeemes_ptr:word
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN msg_flag:byte ;AN022;
EXTRN print_err_flag:word ;AN000;
EXTRN RESSEG:WORD
EXTRN String_ptr_2:word ;AC000;
EXTRN Subst_buffer:byte ;AN061;
;AD061; EXTRN String_ptr_2_sb:word ;AN000;
; include data area for message services
MSG_UTILNAME <COMMAND> ;AN000; define utility name
MSG_SERVICES <MSGDATA> ;AN000;
PRINTF_HANDLE DW ? ;AC000;
TRANSPACE ENDS ;AC000;
TRANCODE SEGMENT PUBLIC BYTE ;AC000;
EXTRN cerror:near
EXTRN crlf2:near
EXTRN tcommand:near ;AN026;
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:NOTHING,SS:NOTHING ;AC000;
PUBLIC SETSTDINOFF ;AN026;
PUBLIC SETSTDINON ;AN026;
PUBLIC SETSTDOUTOFF ;AN026;
PUBLIC SETSTDOUTON ;AN026;
PUBLIC TSYSGETMSG ;AN000;
PUBLIC TSYSLOADMSG ;AN000;
PUBLIC Printf_Init
printf_init proc far
call std_printf
ret
printf_init endp
Public Printf_Crlf
PRINTF_CRLF:
CALL STD_PRINTF
CALL CRLF2
RET
PUBLIC Std_EPrintf
STD_EPRINTF:
mov Printf_Handle,2 ;AC000;Print to STDERR
jmp short NEW_PRINTF ;AC000;
PUBLIC Std_Printf
STD_PRINTF:
mov Printf_Handle,1 ;AC000;Print to STDOUT
NEW_PRINTF:
push ax ;AN000;save registers
push bx ;AN000;
push cx ;AN000;
push es ;AN000;get local ES
push ds ;AN000;
pop es ;AN000;
push di ;AN000;
push si ;AN000;
push dx ;AN000;
assume es:trangroup ;AN000;
;AD061; mov string_ptr_2_sb,0 ;AN000;initialize
mov print_err_flag,0 ;AN000;
UTILITY_SETUP:
mov si,dx ;AN000;Get offset of message number
lodsw ;AN000;load message number
push ax ;AN000;save it
lodsb ;AN000;get number of substitutions
mov cl,al ;AN000;set up CX as # of subst
xor ch,ch ;AN000; SI now points to subst list
pop ax ;AN000;get message number back
cmp cx,0 ;AN000;Any substitutions?
jz READY_TO_PRINT ;AN000;No - continue
;AD061; add dx,Ptr_Seg_Pos ;AN000;Point to position of first segment
;AD061; push cx ;AN000;save substitution count
;AD061;SET_SUBST:
;AD061; mov bx,dx ;AN000;get dx into base register
;AD061; cmp word ptr [bx],0 ;AN000;has segment been set?
;AD061; jnz SUBST_SEG_SET ;AN000;if not 0, don't replace it
;AD061; test word ptr [bx+3],date_type ;AN000;if date or time - don't set segment
;AD061; jnz subst_seg_set ;AN000;yes - skip it
;AD061; mov word ptr [bx],cs ;AN000;put segment of subst parm in list
;AD061;SUBST_SEG_SET:
;AD061; add dx,Parm_Block_Size ;AN000;point to position of next segment
;AD061; loop SET_SUBST ;AN000;keep replacing until complete
;AD061; pop cx ;AN000;
;AD061;NO_REPLACEMENT:
;AD061; mov bx,parm_off_pos [si] ;AN000;get subst offset
;AD061; cmp bx,offset trangroup:string_ptr_2 ;AN000;this is used for double indirection
;AD061; jnz ready_to_print ;AN000;we already have address
;AD061; mov dx,string_ptr_2 ;AN000;get address in string_ptr_2
;AD061; mov parm_off_pos [si],dx ;AN000;put proper address in table
;AD061; mov string_ptr_2_sb,si ;AN000;save block changed
mov di,offset trangroup:subst_buffer;AN061; Get address of message subst buffer
push di ;AN061; save it
push cx ;AN061; save number of subst
MOVE_SUBST:
push cx ;AN061;save number of subst
mov bx,si ;AN061;save start of sublist
mov cx,parm_block_size ;AN061;get size of sublist
rep movsb ;AN061;move sublist
test byte ptr [bx.$M_S_FLAG],date_type ;AN061;are we doing date/time?
jz move_subst_cont ;AN061;no - no need to reset
mov word ptr [bx.$M_S_VALUE],0 ;AN061;reset original date or time to 0
mov word ptr [bx.$M_S_VALUE+2],0 ;AN061;
MOVE_SUBST_CONT: ;AN061;
pop cx ;AN061;get number of subst back
loop move_subst ;AN061;move cx sublists
pop cx ;AN061;get number of subst
push ax ;AN061;save message number
cmp Msg_Disp_Class,Util_Msg_Class ;AN061;Is this a utility message
jz CHECK_FIX ;AN061;YES - go see if substitutions
mov msg_flag,ext_msg_class ;AN061;set message flag
mov di,offset trangroup:extend_buf_ptr ;AN061; Get address of extended message block
xor ax,ax ;AN061;clear ax register
stosw ;AN061;clear out message number
stosb ;AN061;clear out subst count
CHECK_FIX: ;AN061;
pop ax ;AN061;get message number back
pop di ;AN061;get start of sublists
mov si,di ;AN061;get into SI for msgserv
mov bx,si ;AN061;get into BX for addressing
push cx ;AN061;save number of subst
SET_SUBST: ;AN061;store the segment of the subst
cmp word ptr [bx.$M_S_VALUE+2],0 ;AN061;was it set already?
jnz subst_seg_set ;AN061;if not 0, don't replace it
test byte ptr [bx.$M_S_FLAG],date_type ;AN061;don't replace if date or time
jnz subst_seg_set ;AN061;yes - skip it
mov word ptr [bx.$M_S_VALUE+2],cs ;AN061;set segment value
SUBST_SEG_SET: ;AN061;
add bx,parm_block_size ;AN061;go to next sublist
loop set_subst ;AN061;loop CX times
pop cx ;AN061;get number of subst back
mov bx,si ;AN061;get start of sublist to BX
cmp word ptr [bx.$M_S_VALUE],offset trangroup:string_ptr_2 ;AN061;are we using double indirection?
jnz ready_to_print ;AN061;no - we already have address
mov dx,string_ptr_2 ;AN061;get address in string_ptr_2
mov word ptr [bx.$M_S_VALUE],dx ;AN061;put it into the subst block
READY_TO_PRINT:
mov bx,Printf_Handle ;AN000;get print handle
mov dl,Msg_Cont_Flag ;AN000;set up control flag
mov dh,Msg_Disp_Class ;AN000;set up display class
mov Msg_Cont_Flag,No_Cont_Flag ;AN061;reset flags to avoid
mov Msg_Disp_Class,Util_Msg_Class ;AN061; transient reload
;AD061; push bx ;AN026; save registers
;AD061; push cx ;AN026;
;AD061; push dx ;AN026;
;AD061; push si ;AN026;
;AD061; push di ;AN026;
push ds ;AN026;
push es ;AN026;
call SYSDISPMSG ;AN000;call Rod
pop es ;AN026; restore registers
pop ds ;AN026;
;AD061; pop di ;AN026;
;AD061; pop si ;AN026;
;AD061; pop dx ;AN026;
;AD061; pop cx ;AN026;
;AD061; pop bx ;AN026;
jnc Print_success ;AN000; everything went okay
mov print_err_flag,ax ;AN000;
print_success:
;AD061; cmp Msg_Disp_Class,Util_Msg_Class ;AN000;Is this a utility message
;AD061; jz CHECK_FIX ;AN000;YES - go see if substitutions
;AD061; mov msg_flag,ext_msg_class ;AN022;set message flag
;AD061; mov di,offset trangroup:extend_buf_ptr ;AN000; Get address of extended message block
;AD061; xor ax,ax ;AN000;clear ax register
;AD061; stosw ;AN000;clear out message number
;AD061; stosb ;AN000;clear out subst count
;AD061; CHECK_FIX:
;AD061; pop dx ;AN000;restore dx
;AD061; cmp cx,0 ;AN000;Any substitutions?
;AD061; jz NO_FIXUP ;AN000;No - leave
;AD061; mov si,dx ;AN000;Reset changes so transient won't reload
;AD061; add si,Ptr_Seg_Pos ;AN000;Point to position of first segment
;AD061;FIX_SUBST:
;AD061; mov word ptr [si],0 ;AN000;reset segment to 0
;AD061; add si,Parm_Block_Size ;AN000;point to position of next segment
;AD061; loop FIX_SUBST ;AN000;keep replacing until complete
;AD061; cmp string_ptr_2_sb,no_subst ;AN000;was double indirection used?
;AD061; jz no_fixup ;AN000;no - we're finished
;AD061; mov si,string_ptr_2_sb ;AN000;get offset changed
;AD061; mov parm_off_pos [si],offset trangroup:string_ptr_2 ;AN000; set address back to string_ptr_2
;AD061;NO_FIXUP:
;AD061; mov Msg_Cont_Flag,No_Cont_Flag ;AN000;reset flags to avoid
;AD061; mov Msg_Disp_Class,Util_Msg_Class ;AN000; transient reload
pop dx ;AN061;restore dx
pop si ;AN000;restore registers
pop di ;AN000;
pop es ;AN000;restore registers
pop cx ;AN000;
pop bx ;AN000;
pop ax ;AN000;
cmp print_err_flag,0 ;AN000; if an error occurred - handle it
jnz print_err ;AN000;
ret ;AC000;
print_err:
push cs
pop es
cmp Printf_Handle,2 ;AN026;Print to STDERR?
jnz not_stderr ;AN026;no - continue
jmp tcommand ;AN026;Yes - hopless - just exit
not_stderr:
mov ax,print_err_flag ;AN026;get extended error number back
mov es,[resseg] ; No, set up for error, load the
assume es:resgroup ; right error msg, and jmp to cerror.
test PipeFlag,-1
jz go_to_error
invoke PipeOff
mov dx,offset trangroup:pipeemes_ptr
jmp print_err_exit ;AC000;
go_to_error:
mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class
mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
mov Extend_Buf_ptr,ax ;AN000; get message number in control block
PRINT_ERR_EXIT: ;AC000;
push cs
pop es
JMP CERROR
;****************************************************************
;*
;* ROUTINE: TSYSLOADMSG
;*
;* FUNCTION: Interface to call SYSLOADMSG to avoid duplicate
;* names since these routines are also used in the
;* resident.
;*
;* INPUT: Inputs to SYSLOADMSG
;*
;* OUTPUT: Outputs from SYSLOADMSG
;*
;****************************************************************
TSYSLOADMSG PROC NEAR ;AN000;
push bx ;AN000;
call sysloadmsg ;AN000; call routine
pop bx ;AN000;
ret ;AN000; exit
TSYSLOADMSG ENDP ;AN000;
;****************************************************************
;*
;* ROUTINE: TSYSGETMSG
;*
;* FUNCTION: Interface to call SYSGETMSG to avoid duplicate
;* names since these routines are also used in the
;* resident.
;*
;* INPUT: Inputs to SYSGETMSG
;*
;* OUTPUT: Outputs from SYSGETMSG
;*
;****************************************************************
TSYSGETMSG PROC NEAR ;AN000;
push cx ;AN000;
call sysgetmsg ;AN000; call routine
pop cx ;AN000;
ret ;AN000; exit
TSYSGETMSG ENDP ;AN000;
MSG_SERVICES <COMT,NOVERCHECKmsg,NEARmsg,LOADmsg,NOCHECKSTDIN,NOCHECKSTDOUT,GETmsg> ;AC026; The message services
MSG_SERVICES <COMT,NEARmsg,SETSTDIO,DISPLAYmsg,CHARmsg,NUMmsg,TIMEmsg,DATEmsg> ;AC026; The message services
PRINTF_LAST LABEL WORD
include msgdcl.inc
TRANCODE ENDS
END
|