FreeBSD 10 clang port
[oweals/cde.git] / cde / lib / DtTerm / TermPrim / TermPrimParser.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 #ifndef lint
24 #ifdef  VERBOSE_REV_INFO
25 static char rcs_id[] = "$TOG: TermPrimParser.c /main/2 1999/10/15 12:23:41 mgreess $";
26 #endif  /* VERBOSE_REV_INFO */
27 #endif  /* lint */
28
29 /*                                                                      *
30  * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company               *
31  * (c) Copyright 1993, 1994, 1996 International Business Machines Corp. *
32  * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.                *
33  * (c) Copyright 1993, 1994, 1996 Novell, Inc.                          *
34  * (c) Copyright 1996 Digital Equipment Corporation.                    *
35  * (c) Copyright 1996 FUJITSU LIMITED.                                  *
36  * (c) Copyright 1996 Hitachi.                                          *
37  */
38
39 #include <Xm/Xm.h>
40 #include "TermHeader.h"
41 #include "TermPrimDebug.h"
42 #include "TermPrimP.h"
43 #include "TermPrimParserP.h"
44 #include "TermPrimBuffer.h"
45
46 #if defined (__hpux)
47 /*
48  * On HP MAXINT is defined in both <values.h> and <sys/param.h>
49  */
50 #undef MAXINT
51 #endif
52 #if defined(CSRG_BASED)
53 #define MAXINT INT_MAX
54 #else
55 #include  <values.h>
56 #endif
57
58 #ifdef  BBA
59 #pragma BBA_IGNORE
60 #endif  /*BBA*/
61 static void
62 ParseTrap()
63 {
64     static int count = 0;
65
66     (void) count++;
67 }
68
69 /*
70 ** Parse the character, tell the calling routine if we are not
71 ** in the start state.
72 */
73 Boolean
74 _DtTermPrimParse
75 (
76     Widget          w,
77     unsigned char  *parseChar,
78     int             parseCharLen
79 )
80 {
81     ParserContext   context = GetParserContext(w);
82     StateEntry      thisEntry;
83     StateEntry      thisPreParseEntry;
84
85 #ifdef    NOCODE
86     /*
87     ** This decision should be made somewhere else.
88     */
89     if (tp->t_modes.disp_func == 1)
90     {
91         in_disp_func();
92         return(False);
93     }
94 #endif /* NOCODE */
95
96     if (parseCharLen == 1) {
97         *context->inputChar = *parseChar;
98     } else {
99         (void) memmove(context->inputChar, parseChar, parseCharLen);
100     }
101     context->inputCharLen = parseCharLen;
102
103     if (isDebugFSet('p', 1)) {
104 #ifdef  BBA
105 #pragma BBA_IGNORE
106 #endif  /*BBA*/
107         static unsigned char debugChar;
108         static Boolean first = True;
109         char *c;
110
111         if (parseCharLen == 1) {
112             _DtTermProcessLock();
113             if (first) {
114                 if (!(c = getenv("dttermDebugParseChar"))) {
115                     c = "0x03";
116                 }
117                 debugChar = strtol(c, (char **) 0, 0);
118                 first = False;
119             }
120             _DtTermProcessUnlock();
121
122             if (*parseChar == debugChar) {
123                 ParseTrap();
124                 return 0;
125             }
126         }
127     }
128         
129     /*
130     ** Determine which state entry to use.
131     */
132     thisPreParseEntry = context->stateTable->statePreParseEntry;
133     thisEntry = context->stateTable->stateEntry;
134
135     /* first run through the preParse entry... */
136     if (thisPreParseEntry && (parseCharLen == 1)) {
137         while ((*parseChar < thisPreParseEntry->lower) ||
138                 (*parseChar > thisPreParseEntry->upper)) {
139             thisPreParseEntry++;
140         }
141         /* if we hit the end, ignore it... */
142         if ((0x00 == thisPreParseEntry->lower) &&
143                 (0xff == thisPreParseEntry->upper)) {
144             thisPreParseEntry = (StateEntry) 0;
145         }
146     }
147
148     /* if we hit a valid preParseEntry, then let's execute it and
149      * return...
150      */
151     if (thisPreParseEntry) {
152         /*
153         ** Now change states.  If the next state is NULL, stay in the
154         ** current state.  This is for parse entries that do not break us
155         ** out of the current parse thread.  If we need to bail out of the
156         ** current parse thread, then we have a new state specified and
157         ** will switch to it.  We do this before we execute the function
158         ** incase the function needs to change the state as well...
159         */
160         if (thisPreParseEntry->nextState) {
161             context->stateTable = thisPreParseEntry->nextState;
162         }
163
164         /*
165         ** Execute the action associated with the entry.
166         */
167         if (thisPreParseEntry->action) {
168             (*thisPreParseEntry->action)(w);
169         }
170
171         return(!context->stateTable->startState);
172     }
173
174     /* HACK ALERT!!!!
175      *
176      * We need two different search algorithms - the first to deal
177      * with single byte characters, the second to deal with multi-byte
178      * characters.  For now, we will match multi-byte character with
179      * the parse entry that covers 0..255.  If we find that this will
180      * not work for everything, we may need to rethink this.
181      */
182     if (parseCharLen == 1) {
183         while ((*parseChar < thisEntry->lower) ||
184                 (*parseChar > thisEntry->upper))
185         {
186             thisEntry++;
187         }
188     } else {
189         while ((0x00 != thisEntry->lower) ||
190                 (0xff != thisEntry->upper))
191         {
192             thisEntry++;
193         }
194     }
195         
196     /*
197     ** Now change states.  We do this before we execute the function incase
198     ** the function needs to change the state as well...
199     */
200     context->stateTable = thisEntry->nextState;
201
202     /*
203     ** Execute the action associated with the entry.
204     */
205     if (thisEntry->action) {
206         (*thisEntry->action)(w);
207     }
208
209     return(!context->stateTable->startState);
210 }
211
212 /*
213 **
214 **  _DtTermPrimParserClrStrParm()
215 **
216 **  clrStrParm clears the string parameters.
217 **
218 */
219 void
220 _DtTermPrimParserClrStrParm
221 (
222     Widget w
223 )
224 {
225     ParserContext   context = GetParserContext(w);
226
227     context->stringParms[0].length = 0;
228     (void) memset(context->stringParms[0].str, 0x00, STR_SIZE + 1);
229
230     context->stringParms[1].length = 0;
231     (void) memset(context->stringParms[1].str, 0x00, STR_SIZE + 1);
232 }
233
234 /*
235 **
236 **  _DtTermPrimParserNextState()
237 **
238 **  nextState is a do nothing routine.  It is called when the only
239 **  action that needs to be preformed is changing states in the
240 **  state machine.
241 **
242 */
243 void
244 _DtTermPrimParserNextState
245 (
246     Widget w
247 )
248 {
249 }
250
251 /*
252 **
253 **  _DtTermPrimParserClearParm()
254 **
255 **  _DtTermPrimParserClearParm clears all common parameters.
256 **
257 */
258 void
259 _DtTermPrimParserClearParm
260 (
261     Widget w
262 )
263 {
264     ParserContext  context = GetParserContext(w);
265     int             i;
266
267     for (i = 0; i < NUM_PARMS; i++) {
268         context->parms[i] = 0;
269     }
270     context->workingNum = 0;
271     context->workingNumIsDefault = True;
272     context->sign = TermPARSER_SIGNnone;
273 }
274
275 /*
276 **
277 **  enterNum()
278 **
279 **  enterNum enters a numerical parameter.
280 **
281 */
282 void
283 _DtTermPrimParserEnterNum
284 (
285     Widget w
286 )
287 {
288     ParserContext   context = GetParserContext(w);
289
290     if ( context->workingNum < MAXINT>>4 ) 
291         context->workingNum = context->workingNum * 10 +
292             (*context->inputChar - '0');
293     context->workingNumIsDefault = False;
294 }
295
296 void
297 _DtTermPrimParserSaveSign
298 (
299     Widget w
300 )
301 {
302     ParserContext   context = GetParserContext(w);
303
304     SetSign(context, (*GetInputChar(context) == '-') ? TermPARSER_SIGNnegative :
305             TermPARSER_SIGNpositive);
306 }
307
308 /*
309 **
310 **  _DtTermPrimParserNumParmPush()
311 **
312 **  _DtTermPrimParserNumParmPush() takes the number in workingNum and 
313 **   stores it in parm[parmNum].
314 **
315 */
316 void
317 _DtTermPrimParserNumParmPush
318 (
319     Widget w,
320     int    parmNum
321 )
322 {
323     ParserContext   context = GetParserContext(w);
324
325     if ( parmNum < NUM_PARMS ) {
326       context->parms[parmNum] = context->workingNum;
327       context->workingNum     = 0;
328       context->workingNumIsDefault = False;
329     }
330 }
331
332 /*
333 ** Initialize the context of the parser.
334 */
335 void
336 _DtTermPrimParserInitContext
337 (
338     Widget w
339 )
340 {
341     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
342     DtTermPrimData tpd = tw->term.tpd;
343
344     tpd->context = (ParserContext) XtMalloc(sizeof(ParserContextRec));
345     (void) memset(tpd->context, '\0', sizeof(ParserContextRec));
346
347     tpd->context->stateTable =
348             *(((DtTermPrimitiveClassRec *) (tw->core.widget_class))->
349             term_primitive_class.parser_start_state);
350     tpd->context->stateName  = START;
351 }
352
353 #ifdef TEST
354
355 #include <ctype.h>
356
357 #define testFunction(f) \
358 void f ( Widget w ) {printf(#f " called.\n");}
359
360 int cursor_col, cursor_row;
361 int logical_col, logical_row;
362
363 testFunction(_termCR)
364 testFunction(_termLF)
365 testFunction(_termTab)
366 testFunction(_termBackspace)
367 testFunction(RecordDC1Rcvd)
368 testFunction(_termWriteChar)
369 testFunction(_DtTermPrimBell)
370 testFunction(_termShiftOut)
371 testFunction(_termShiftIn)
372 testFunction(set_tab)
373 testFunction(clear_tab)
374 testFunction(clr_all_tab)
375 testFunction(set_left_marg)
376 testFunction(set_right_marg)
377 testFunction(clear_marg)
378 testFunction(curs_up)
379 testFunction(curs_down)
380 testFunction(curs_right)
381 testFunction(curs_left)
382 testFunction(home_down)
383 testFunction(home_up)
384 testFunction(clr_display)
385 testFunction(clear_line)
386 testFunction(insert_line)
387 testFunction(delete_line)
388 testFunction(delete_char)
389 testFunction(insert_char)
390 testFunction(off_insert_char)
391 testFunction(roll_up)
392 testFunction(roll_down)
393 testFunction(next_page)
394 testFunction(prev_page)
395 testFunction(format_mode_on)
396 testFunction(format_mode_off)
397 testFunction(display_func)
398 testFunction(term_status)
399 testFunction(rel_curs_pos)
400 testFunction(abs_curs_pos)
401 testFunction(enable_key)
402 testFunction(disable_key)
403 testFunction(enter_line)
404 testFunction(back_tab)
405 testFunction(user_key_menu_on)
406 testFunction(user_key_menu_off)
407 testFunction(second_status)
408 testFunction(mlock_on)
409 testFunction(mlock_off)
410 testFunction(start_unprotect)
411 testFunction(stop_field)
412
413 void
414 _parserPrintContext
415 (
416     ParserContext   context
417 )
418 {
419     printf("    inputChar  : ");
420     if (isprint(*context->inputChar))
421     {
422         printf("'%c'\n", *context->inputChar);
423     }
424     else
425     {
426         printf("\x2X\n", *context->inputChar);
427     }
428     for (i = 0; i < 9; i++)
429     {
430         printf("    parm[%d]      : %d\n", i, context->parm[i]);
431     }
432     printf("    workingNum : %d\n", context->workingNum);
433 }
434
435 void
436 parseString
437 (
438     Widget          w;
439     unsigned char  *string
440 )
441 {
442     ParserContext   context = GetParserContext(w);
443     int i;
444
445     _parserPrintContext(context);
446     for (i = 0; i < strlen((char *)string); i++)
447     {
448         _DtTermPrimParse(context, string[i]);
449         _parserPrintContext(context);
450     }
451 }
452
453 /* the following is to allow for a single main function in the code... */
454 #define parserMain      main
455 parserMain()
456 {
457     parserContext   context;
458
459     _parserInitContext(&context);
460
461     cursor_col = 0;
462     cursor_row = 0;
463
464     logical_col = 5;
465     logical_row = 5;
466
467     printf("\nparsing <esc>&a5r5C\n");
468     parseString(&context, (unsigned char *)"\033&a5r5C");
469
470     printf("\nparsing <esc>a5r35C\n");
471     parseString(&context, (unsigned char *)"\033&a5r35C");
472
473     printf("\nparsing <esc>&a5r3r4c5C\n");
474     parseString(&context, (unsigned char *)"\033&a5r3r4c5C");
475
476     printf("\nparsing <esc>&arC\n");
477     parseString(&context, (unsigned char *)"\033&arC");
478
479     printf("\nparsing <esc>&a5C\n");
480     parseString(&context, (unsigned char *)"\033&a5C");
481
482     printf("\nparsing <esc>&a+5C\n");
483     parseString(&context, (unsigned char *)"\033&a+5C");
484 }
485 #endif /* TEST */