tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / bin / pc / pc.c
blobefd90924a36fda70821aa11f879130edfeaba452
1 /*
2 PC -- programmer's calculator.
4 This program implements a simple recursive descent parser that
5 understands pretty much all standard C language math and logic
6 expressions. It handles the usual add, subtract, multiply, divide,
7 and mod sort of stuff. It can also deal with logical/relational
8 operations and expressions. The logic/relational operations AND, OR,
9 NOT, and EXCLUSIVE OR, &&, ||, ==, !=, <, >, <=, and >= are all
10 supported. It also handles parens and nested expresions as well as
11 left and right shifts. There are variables and assignments (as well
12 as assignment operators like "*=").
14 The other useful feature is that you can use "." in an expression
15 to refer to the value from the previous expression (just like bc).
17 Multiple statements can be separated by semi-colons (;) on a single
18 line (though a single statement can't span multiple lines).
20 This calculator is mainly a programmers calculator because it
21 doesn't work in floating point and only deals with integers.
23 I wrote this because the standard unix calculator (bc) doesn't
24 offer a useful modulo, it doesn't have left and right shifts and
25 sometimes it is a pain in the ass to use (but I still use bc for
26 things that require any kind of floating point). This program is
27 great when you have to do address calculations and bit-wise
28 masking/shifting as you do when working on kernel type code. It's
29 also handy for doing quick conversions between decimal, hex and ascii
30 (and if you want to see octal for some reason, just put it in the
31 printf string).
33 The parser is completely separable and could be spliced into other
34 code very easy. The routine parse_expression() just expects a char
35 pointer and returns the value. Implementing command line editing
36 would be easy using a readline() type of library.
38 This isn't the world's best parser or anything, but it works and
39 suits my needs. It faithfully implements C style precedence of
40 operators for:
42 ++ -- ~ ! * / % + - << >> < > <= >= == != & ^ | && ||
44 (in that order, from greatest to least precedence).
46 Note: The ! unary operator is a logical negation, not a bitwise
47 negation (if you want bitwise negation, use ~).
49 I've been working on adding variables and assignments, and I've
50 just (10/26/94) got it working right and with code I'm not ashamed of.
51 Now you can have variables (no restrictions on length) and assign to
52 them and use them in expressions. Variable names have the usual C
53 rules (i.e. alpha or underscore followed by alpha-numeric and
54 underscore). Variables are initialized to zero and created as needed.
55 You can have any number of variables. Here are some examples:
57 x = 5
58 x = y = 10
59 x = (y + 5) * 2
60 (y * 2) + (x & 0xffeef)
63 Assignment operators also work. The allowable assignment operators
64 are (just as in C):
66 +=, -=, *=, /=, %=, &=, ^=, |=, <<=, and >>=
69 The basic ideas for this code came from the book "Compiler Design
70 in C", by Allen I. Holub, but I've extended them significantly.
72 If you find bugs or parsing bogosites, I'd like to know about them
73 so I can fix them. Other comments and criticism of the code are
74 welcome as well.
76 Thanks go to Joel Tesler (joel@engr.sgi.com) for adding the ability
77 to pass command line arguments and have pc evaluate them instead of reading
78 from stdin.
80 Dominic Giampaolo
81 dbg@be.com (though this was written while I was at sgi)
83 #include <stdio.h>
84 #include <stdlib.h>
85 #include <limits.h>
86 #include <string.h>
87 #include <ctype.h>
88 #include "lex.h"
92 * You should #define USE_LONG_LONG if your compiler supports the long long
93 * data type, has strtoull(), and a %lld conversion specifier for printf.
94 * Otherwise just comment out the #define and pc will use plain longs.
97 #define USE_LONG_LONG
100 #ifdef USE_LONG_LONG
101 #define LONG long long
102 #define ULONG unsigned long long
103 #define STRTOUL strtoull
104 #define STR1 "%20llu 0x%.16llx signed: %20lld"
105 #define STR2 "%20llu 0x%.16llx"
106 #define STR3 " char: "
107 #define STR4 "%20lu 0x%-16.8lx signed: %20ld"
108 #define STR5 "%20lu 0x%-16.8lx"
109 #else
110 #define LONG long
111 #define ULONG unsigned long
112 #define STRTOUL strtoul
113 #define STR1 "%10lu\t 0x%.8lx\t signed: %10ld"
114 #define STR2 "%10lu\t 0x%.8lx"
115 #define STR3 " char: "
116 #define STR4 STR1
117 #define STR5 STR2
118 #endif
121 ULONG parse_expression(char *str); /* top-level interface to parser */
122 ULONG assignment_expr(char **str); /* assignments =, +=, *=, etc */
123 ULONG do_assignment_operator(char **str, char *var_name);
124 ULONG logical_or_expr(char **str); /* logical OR `||' */
125 ULONG logical_and_expr(char **str); /* logical AND `&&' */
126 ULONG or_expr(char **str); /* OR `|' */
127 ULONG xor_expr(char **str); /* XOR `^' */
128 ULONG and_expr(char **str); /* AND `&' */
129 ULONG equality_expr(char **str); /* equality ==, != */
130 ULONG relational_expr(char **str); /* relational <, >, <=, >= */
131 ULONG shift_expr(char **str); /* shifts <<, >> */
132 ULONG add_expression(char **str); /* addition/subtraction +, - */
133 ULONG term(char **str); /* multiplication/division *,%,/ */
134 ULONG factor(char **str); /* negation, logical not ~, ! */
135 ULONG get_value(char **str);
136 int get_var(char *name, ULONG *val); /* external interfaces to vars */
137 ULONG set_var(char *name, ULONG val);
139 void do_input(void); /* reads stdin and calls parser */
140 char *skipwhite(char *str); /* skip over input white space */
145 * Variables are kept in a simple singly-linked list. Not high
146 * performance, but it's also an extremely small implementation.
148 * New variables get added to the head of the list. Variables are
149 * never deleted, though it wouldn't be hard to do that.
152 typedef struct variable
154 char *name;
155 ULONG value;
156 struct variable *next;
157 }variable;
159 variable dummy = { NULL, 0L, NULL };
160 variable *vars=&dummy;
162 variable *lookup_var(char *name);
163 variable *add_var(char *name, ULONG value);
164 char *get_var_name(char **input_str);
165 void parse_args(int argc, char *argv[]);
166 int (*set_var_lookup_hook(int (*func)(char *name, ULONG *val)))
167 (char *name, ULONG *val);
170 * last_result is equal to the result of the last expression and
171 * expressions can refer to it as `.' (just like bc).
173 ULONG last_result = 0;
176 static int
177 special_vars(char *name, ULONG *val)
179 if (strcmp(name, "time") == 0)
180 *val = (ULONG)time(NULL);
181 else if (strcmp(name, "rand") == 0)
182 *val = (ULONG)rand();
183 else if (strcmp(name, "dbg") == 0)
184 *val = 0x82969;
185 else
186 return 0;
188 return 1;
193 main(int argc, char *argv[])
196 set_var_lookup_hook(special_vars);
198 if (argc > 1)
199 parse_args(argc, argv);
200 else
201 do_input();
203 return 0;
207 This function prints the result of the expression.
208 It tries to be smart about printing numbers so it
209 only uses the necessary number of digits. If you
210 have long long (i.e. 64 bit numbers) it's very
211 annoying to have lots of leading zeros when they
212 aren't necessary. By doing the somewhat bizarre
213 casting and comparisons we can determine if a value
214 will fit in a 32 bit quantity and only print that.
216 static void
217 print_result(ULONG value)
219 int i;
220 ULONG ch, shift;
222 if ((signed LONG)value < 0)
224 if ((signed LONG)value < (signed LONG)(LONG_MIN))
225 printf(STR1, value, value, value);
226 else
227 printf(STR4, (long)value, (long)value, (long)value);
229 else if ((ULONG)value <= (ULONG)ULONG_MAX)
230 printf(STR5, (long)value, (long)value);
231 else
232 printf(STR2, value, value);
235 Print any printable character (and print dots for unprintable chars
237 printf(STR3);
238 for(i=sizeof(ULONG)-1; i >= 0; i--)
240 shift = i * 8;
241 ch = ((ULONG)value & ((ULONG)0xff << shift)) >> shift;
243 if (isprint((int)ch))
244 printf("%c", (char)(ch));
245 else
246 printf(".");
249 printf("\n");
252 void
253 parse_args(int argc, char *argv[])
255 int i, len;
256 char *buff;
257 ULONG value;
259 for(i=1, len=0; i < argc; i++)
260 len += strlen(argv[i]);
261 len++;
263 buff = malloc(len*sizeof(char));
264 if (buff == NULL)
265 return;
267 buff[0] = '\0';
268 while (--argc > 0)
270 strcat(buff, *++argv);
272 value = parse_expression(buff);
274 print_result(value);
276 free(buff);
279 void
280 do_input(void)
282 ULONG value;
283 char buff[256], *ptr;
285 while(fgets(buff, 256, stdin) != NULL)
287 if (buff[strlen(buff)-1] == '\n')
288 buff[strlen(buff)-1] = '\0'; /* kill the newline character */
290 for(ptr=buff; isspace(*ptr) && *ptr; ptr++)
291 /* skip whitespace */;
293 if (*ptr == '\0') /* hmmm, an empty line, just skip it */
294 continue;
296 value = parse_expression(buff);
298 print_result(value);
303 ULONG
304 parse_expression(char *str)
306 ULONG val;
307 char *ptr = str;
309 ptr = skipwhite(ptr);
310 if (*ptr == '\0')
311 return last_result;
313 val = assignment_expr(&ptr);
315 ptr = skipwhite(ptr);
316 while (*ptr == SEMI_COLON && *ptr != '\0')
318 ptr++;
319 if (*ptr == '\0') /* reached the end of the string, stop parsing */
320 continue;
322 val = assignment_expr(&ptr);
325 last_result = val;
326 return val;
330 ULONG
331 assignment_expr(char **str)
333 ULONG val;
334 char *orig_str;
335 char *var_name;
336 variable *v;
338 *str = skipwhite(*str);
339 orig_str = *str;
341 var_name = get_var_name(str);
343 *str = skipwhite(*str);
344 if (**str == EQUAL && *(*str+1) != EQUAL)
346 *str = skipwhite(*str + 1); /* skip the equal sign */
348 val = assignment_expr(str); /* go recursive! */
350 if ((v = lookup_var(var_name)) == NULL)
351 add_var(var_name, val);
352 else
353 v->value = val;
355 else if (((**str == PLUS || **str == MINUS || **str == OR ||
356 **str == TIMES || **str == DIVISION || **str == MODULO ||
357 **str == AND || **str == XOR) && *(*str+1) == EQUAL) ||
358 strncmp(*str, "<<=", 3) == 0 || strncmp(*str, ">>=", 3) == 0)
360 val = do_assignment_operator(str, var_name);
362 else
364 *str = orig_str;
365 val = logical_or_expr(str); /* no equal sign, just get var value */
367 *str = skipwhite(*str);
368 if (**str == EQUAL)
370 fprintf(stderr, "Left hand side of expression is not assignable.\n");
374 if (var_name)
375 free(var_name);
377 return val;
381 ULONG
382 do_assignment_operator(char **str, char *var_name)
384 ULONG val;
385 variable *v;
386 char operator;
388 operator = **str;
390 if (operator == SHIFT_L || operator == SHIFT_R)
391 *str = skipwhite(*str + 3);
392 else
393 *str = skipwhite(*str + 2); /* skip the assignment operator */
395 val = assignment_expr(str); /* go recursive! */
397 v = lookup_var(var_name);
398 if (v == NULL)
400 v = add_var(var_name, 0);
401 if (v == NULL)
402 return 0;
405 if (operator == PLUS)
406 v->value += val;
407 else if (operator == MINUS)
408 v->value -= val;
409 else if (operator == AND)
410 v->value &= val;
411 else if (operator == XOR)
412 v->value ^= val;
413 else if (operator == OR)
414 v->value |= val;
415 else if (operator == SHIFT_L)
416 v->value <<= val;
417 else if (operator == SHIFT_R)
418 v->value >>= val;
419 else if (operator == TIMES)
420 v->value *= val;
421 else if (operator == DIVISION)
423 if (val == 0) /* check for it, but still get the result */
424 fprintf(stderr, "Divide by zero!\n");
426 v->value /= val;
428 else if (operator == MODULO)
430 if (val == 0) /* check for it, but still get the result */
431 fprintf(stderr, "Modulo by zero!\n");
433 v->value %= val;
435 else
437 fprintf(stderr, "Unknown operator: %c\n", operator);
438 v->value = 0;
441 return v->value;
445 ULONG
446 logical_or_expr(char **str)
448 ULONG val, sum = 0;
450 *str = skipwhite(*str);
452 sum = logical_and_expr(str);
454 *str = skipwhite(*str);
455 while(**str == OR && *(*str + 1) == OR)
457 *str = skipwhite(*str + 2); /* advance over the operator */
459 val = logical_and_expr(str);
461 sum = (val || sum);
464 return sum;
469 ULONG
470 logical_and_expr(char **str)
472 ULONG val, sum = 0;
474 *str = skipwhite(*str);
476 sum = or_expr(str);
478 *str = skipwhite(*str);
479 while(**str == AND && *(*str + 1) == AND)
481 *str = skipwhite(*str + 2); /* advance over the operator */
483 val = or_expr(str);
485 sum = (val && sum);
488 return sum;
492 ULONG
493 or_expr(char **str)
495 ULONG val, sum = 0;
497 *str = skipwhite(*str);
499 sum = xor_expr(str);
501 *str = skipwhite(*str);
502 while(**str == OR && *(*str+1) != OR)
504 *str = skipwhite(*str + 1); /* advance over the operator */
506 val = xor_expr(str);
508 sum |= val;
511 return sum;
516 ULONG
517 xor_expr(char **str)
519 ULONG val, sum = 0;
521 *str = skipwhite(*str);
523 sum = and_expr(str);
525 *str = skipwhite(*str);
526 while(**str == XOR)
528 *str = skipwhite(*str + 1); /* advance over the operator */
530 val = and_expr(str);
532 sum ^= val;
535 return sum;
540 ULONG
541 and_expr(char **str)
543 ULONG val, sum = 0;
545 *str = skipwhite(*str);
547 sum = equality_expr(str);
549 *str = skipwhite(*str);
550 while(**str == AND && *(*str+1) != AND)
552 *str = skipwhite(*str + 1); /* advance over the operator */
554 val = equality_expr(str);
556 sum &= val;
559 return sum;
563 ULONG
564 equality_expr(char **str)
566 ULONG val, sum = 0;
567 char op;
569 *str = skipwhite(*str);
571 sum = relational_expr(str);
573 *str = skipwhite(*str);
574 while((**str == EQUAL && *(*str+1) == EQUAL) ||
575 (**str == BANG && *(*str+1) == EQUAL))
577 op = **str;
579 *str = skipwhite(*str + 2); /* advance over the operator */
581 val = relational_expr(str);
583 if (op == EQUAL)
584 sum = (sum == val);
585 else if (op == BANG)
586 sum = (sum != val);
589 return sum;
593 ULONG
594 relational_expr(char **str)
596 ULONG val, sum = 0;
597 char op, equal_to=0;
599 *str = skipwhite(*str);
601 sum = shift_expr(str);
603 *str = skipwhite(*str);
604 while(**str == LESS_THAN || **str == GREATER_THAN)
606 equal_to = 0;
607 op = **str;
609 if (*(*str+1) == EQUAL)
611 equal_to = 1;
612 *str = *str+1; /* skip initial operator */
615 *str = skipwhite(*str + 1); /* advance over the operator */
617 val = shift_expr(str);
620 Notice that we do the relational expressions as signed
621 comparisons. This is because of expressions like:
622 0 > -1
623 which would not return the expected value if we did the
624 comparison as unsigned. This may not always be the
625 desired behavior, but aside from adding casting to epxressions,
626 there isn't much of a way around it.
628 if (op == LESS_THAN && equal_to == 0)
629 sum = ((LONG)sum < (LONG)val);
630 else if (op == LESS_THAN && equal_to == 1)
631 sum = ((LONG)sum <= (LONG)val);
632 else if (op == GREATER_THAN && equal_to == 0)
633 sum = ((LONG)sum > (LONG)val);
634 else if (op == GREATER_THAN && equal_to == 1)
635 sum = ((LONG)sum >= (LONG)val);
638 return sum;
642 ULONG
643 shift_expr(char **str)
645 ULONG val, sum = 0;
646 char op;
648 *str = skipwhite(*str);
650 sum = add_expression(str);
652 *str = skipwhite(*str);
653 while((strncmp(*str, "<<", 2) == 0) || (strncmp(*str, ">>", 2) == 0))
655 op = **str;
657 *str = skipwhite(*str + 2); /* advance over the operator */
659 val = add_expression(str);
661 if (op == SHIFT_L)
662 sum <<= val;
663 else if (op == SHIFT_R)
664 sum >>= val;
667 return sum;
673 ULONG
674 add_expression(char **str)
676 ULONG val, sum = 0;
677 char op;
679 *str = skipwhite(*str);
681 sum = term(str);
683 *str = skipwhite(*str);
684 while(**str == PLUS || **str == MINUS)
686 op = **str;
688 *str = skipwhite(*str + 1); /* advance over the operator */
690 val = term(str);
692 if (op == PLUS)
693 sum += val;
694 else if (op == MINUS)
695 sum -= val;
698 return sum;
704 ULONG
705 term(char **str)
707 ULONG val, sum = 0;
708 char op;
711 sum = factor(str);
712 *str = skipwhite(*str);
715 * We're at the bottom of the parse. At this point we either have
716 * an operator or we're through with this string. Otherwise it's
717 * an error and we print a message.
719 if (**str != TIMES && **str != DIVISION && **str != MODULO &&
720 **str != PLUS && **str != MINUS && **str != OR &&
721 **str != AND && **str != XOR && **str != BANG &&
722 **str != NEGATIVE && **str != TWIDDLE && **str != RPAREN &&
723 **str != LESS_THAN && **str != GREATER_THAN && **str != SEMI_COLON &&
724 strncmp(*str, "<<", 2) != 0 && strncmp(*str, ">>", 2) &&
725 **str != EQUAL && **str != '\0')
727 fprintf(stderr, "Parsing stopped: unknown operator %s\n", *str);
728 return sum;
731 while(**str == TIMES || **str == DIVISION || **str == MODULO)
733 op = **str;
734 *str = skipwhite(*str + 1);
735 val = factor(str);
737 if (op == TIMES)
738 sum *= val;
739 else if (op == DIVISION)
741 if (val == 0)
742 fprintf(stderr, "Divide by zero!\n");
744 sum /= val;
746 else if (op == MODULO)
748 if (val == 0)
749 fprintf(stderr, "Modulo by zero!\n");
751 sum %= val;
755 return sum;
759 ULONG
760 factor(char **str)
762 ULONG val=0;
763 char op = NOTHING, have_special=0;
764 char *var_name, *var_name_ptr;
765 variable *v;
767 if (**str == NEGATIVE || **str == PLUS || **str == TWIDDLE || **str == BANG)
769 op = **str; /* must be a unary op */
771 if ((op == NEGATIVE && *(*str + 1) == NEGATIVE) || /* look for ++/-- */
772 (op == PLUS && *(*str + 1) == PLUS))
774 *str = *str + 1;
775 have_special = 1;
778 *str = skipwhite(*str + 1);
779 var_name_ptr = *str; /* save where the varname should be */
782 val = get_value(str);
784 *str = skipwhite(*str);
787 * Now is the time to actually do the unary operation if one
788 * was present.
790 if (have_special) /* we've got a ++ or -- */
792 var_name = get_var_name(&var_name_ptr);
793 if (var_name == NULL)
795 fprintf(stderr, "Can only use ++/-- on variables.\n");
796 return val;
798 if ((v = lookup_var(var_name)) == NULL)
800 v = add_var(var_name, 0);
801 if (v == NULL)
802 return val;
804 free(var_name);
806 if (op == PLUS)
807 val = ++v->value;
808 else
809 val = --v->value;
811 else /* normal unary operator */
813 switch(op)
815 case NEGATIVE : val *= -1;
816 break;
818 case BANG : val = !val;
819 break;
821 case TWIDDLE : val = ~val;
822 break;
826 return val;
831 ULONG
832 get_value(char **str)
834 ULONG val;
835 char *var_name;
836 variable *v;
838 if (**str == SINGLE_QUOTE) /* a character constant */
840 unsigned int i;
842 *str = *str + 1; /* advance over the leading quote */
843 val = 0;
844 for(i=0; **str && **str != SINGLE_QUOTE && i < sizeof(LONG); *str+=1,i++)
846 if (**str == '\\') /* escape the next char */
847 *str += 1;
849 val <<= 8;
850 val |= (ULONG)((unsigned)**str);
853 if (**str != SINGLE_QUOTE) /* constant must have been too long */
855 fprintf(stderr, "Warning: character constant not terminated or too "
856 "long (max len == %ld bytes)\n", sizeof(LONG));
857 while(**str && **str != SINGLE_QUOTE)
858 *str += 1;
860 else if (**str != '\0')
861 *str += 1;
863 else if (isdigit(**str)) /* a regular number */
865 val = STRTOUL(*str, str, 0);
867 *str = skipwhite(*str);
869 else if (**str == USE_LAST_RESULT) /* a `.' meaning use the last result */
871 val = last_result;
872 *str = skipwhite(*str+1);
874 else if (**str == LPAREN) /* a parenthesized expression */
876 *str = skipwhite(*str + 1);
878 val = assignment_expr(str); /* start at top and come back down */
880 if (**str == RPAREN)
881 *str = *str + 1;
882 else
883 fprintf(stderr, "Mismatched paren's\n");
885 else if (isalpha(**str) || **str == '_') /* a variable name */
887 if ((var_name = get_var_name(str)) == NULL)
889 fprintf(stderr, "Can't get var name!\n");
890 return 0;
893 if (get_var(var_name, &val) == 0)
895 fprintf(stderr, "No such variable: %s (assigning value of zero)\n",
896 var_name);
898 val = 0;
899 v = add_var(var_name, val);
900 if (v == NULL)
901 return 0;
904 *str = skipwhite(*str);
905 if (strncmp(*str, "++", 2) == 0 || strncmp(*str, "--", 2) == 0)
907 if ((v = lookup_var(var_name)) != NULL)
909 val = v->value;
910 if (**str == '+')
911 v->value++;
912 else
913 v->value--;
914 *str = *str + 2;
916 else
918 fprintf(stderr, "%s is a read-only variable\n", var_name);
922 free(var_name);
924 else
926 fprintf(stderr, "Expecting left paren, unary op, constant or variable.");
927 fprintf(stderr, " Got: `%s'\n", *str);
928 return 0;
932 return val;
937 * Here are the functions that manipulate variables.
941 this is a hook function for external read-only
942 variables. If it is set and we don't find a
943 variable name in our name space, we call it to
944 look for the variable. If it finds the name, it
945 fills in val and returns 1. If it returns 0, it
946 didn't find the variable.
948 static int (*external_var_lookup)(char *name, ULONG *val) = NULL;
951 this very ugly function declaration is for the function
952 set_var_lookup_hook which accepts one argument, "func", which
953 is a pointer to a function that returns int (and accepts a
954 char * and ULONG *). set_var_lookup_hook returns a pointer to
955 a function that returns int and accepts char * and ULONG *.
957 It's very ugly looking but fairly basic in what it does. You
958 pass in a function to set as the variable name lookup up hook
959 and it passes back to you the old function (which you should
960 call if it is non-null and your function fails to find the
961 variable name).
963 int (*set_var_lookup_hook(int (*func)(char *name, ULONG *val)))(char *name, ULONG *val)
965 int (*old_func)(char *name, ULONG *val) = external_var_lookup;
967 external_var_lookup = func;
969 return old_func;
973 variable *
974 lookup_var(char *name)
976 variable *v;
978 for(v=vars; v; v=v->next)
979 if (v->name && strcmp(v->name, name) == 0)
980 return v;
982 return NULL;
986 variable *
987 add_var(char *name, ULONG value)
989 variable *v;
990 ULONG tmp;
992 /* first make sure this isn't an external read-only variable */
993 if (external_var_lookup)
994 if (external_var_lookup(name, &tmp) != 0)
996 fprintf(stderr, "Can't assign/create %s, it is a read-only var\n",name);
997 return NULL;
1001 v = (variable *)malloc(sizeof(variable));
1002 if (v == NULL)
1004 fprintf(stderr, "No memory to add variable: %s\n", name);
1005 return NULL;
1008 v->name = strdup(name);
1009 v->value = value;
1010 v->next = vars;
1012 vars = v; /* set head of list to the new guy */
1014 return v;
1018 This routine and the companion get_var() are external
1019 interfaces to the variable manipulation routines.
1021 ULONG
1022 set_var(char *name, ULONG val)
1024 variable *v;
1026 v = lookup_var(name);
1027 if (v != NULL)
1028 v->value = val;
1029 else
1030 add_var(name, val);
1035 This function returns 1 on success of finding
1036 a variable and 0 on failure to find a variable.
1037 If a variable is found, val is filled with its
1038 value.
1041 get_var(char *name, ULONG *val)
1043 variable *v;
1045 v = lookup_var(name);
1046 if (v != NULL)
1048 *val = v->value;
1049 return 1;
1051 else if (external_var_lookup != NULL)
1053 return external_var_lookup(name, val);
1056 return 0;
1059 #define DEFAULT_LEN 32
1061 char *
1062 get_var_name(char **str)
1064 int i, len=DEFAULT_LEN;
1065 char *buff;
1067 if (isalpha(**str) == 0 && **str != '_')
1068 return NULL;
1070 buff = (char *)malloc(len*sizeof(char));
1071 if (buff == NULL)
1072 return NULL;
1075 * First get the variable name
1077 i=0;
1078 while(**str && (isalnum(**str) || **str == '_'))
1080 if (i >= len-1)
1082 len *= 2;
1083 buff = (char *)realloc(buff, len);
1084 if (buff == NULL)
1085 return NULL;
1088 buff[i++] = **str;
1089 *str = *str+1;
1092 buff[i] = '\0'; /* null terminate */
1094 while (isalnum(**str) || **str == '_') /* skip over any remaining junk */
1095 *str = *str+1;
1097 return buff;
1102 char *
1103 skipwhite(char *str)
1105 if (str == NULL)
1106 return NULL;
1108 while(*str && (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\f'))
1109 str++;
1111 return str;