(file) Return to prims.c CVS log (file) (dir) Up to [RizwankCVS] / testProject / states

   1 rizwank 1.1 /*
   2              * Primitive procedures for states.
   3              * Copyright (c) 1997-1999 Markku Rossi.
   4              *
   5              * Author: Markku Rossi <mtr@iki.fi>
   6              */
   7             
   8             /*
   9              * This file is part of GNU enscript.
  10              *
  11              * This program is free software; you can redistribute it and/or modify
  12              * it under the terms of the GNU General Public License as published by
  13              * the Free Software Foundation; either version 2, or (at your option)
  14              * any later version.
  15              *
  16              * This program is distributed in the hope that it will be useful,
  17              * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18              * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19              * GNU General Public License for more details.
  20              *
  21              * You should have received a copy of the GNU General Public License
  22 rizwank 1.1  * along with this program; see the file COPYING.  If not, write to
  23              * the Free Software Foundation, 59 Temple Place - Suite 330,
  24              * Boston, MA 02111-1307, USA.
  25              */
  26             
  27             #include "defs.h"
  28             
  29             /*
  30              * Types and definitions.
  31              */
  32             
  33             #define DEFUN(prim)				\
  34             static Node *					\
  35             prim (prim_name, args, env, filename, linenum)	\
  36                  char *prim_name;				\
  37                  List *args;				\
  38                  Environment *env;				\
  39                  char *filename;				\
  40                  unsigned int linenum;
  41             
  42             #define NEED_ARG()						\
  43 rizwank 1.1 do {								\
  44               if (arg == NULL)						\
  45                 {								\
  46                   fprintf (stderr, _("%s:%d: %s: too few arguments\n"),	\
  47             	       filename, linenum, prim_name);			\
  48                   exit (1);							\
  49                 }								\
  50             } while (0)
  51             
  52             #define LAST_ARG()						\
  53               do {								\
  54                 if (arg != NULL)						\
  55                   {								\
  56             	fprintf (stderr, _("%s:%d: %s: too many arguments\n"),	\
  57             		 filename, linenum, prim_name);			\
  58             	exit (1);						\
  59                   }								\
  60               } while (0)
  61             
  62             #define MATCH_ARG(type) \
  63               match_arg (prim_name, type, &arg, env, filename, linenum)
  64 rizwank 1.1 
  65             #define APPEND(data, len)				\
  66               do {							\
  67                 if (result_len < result_pos + (len))		\
  68                   {							\
  69             	result_len += (len) + 1024;			\
  70             	result = xrealloc (result, result_len);		\
  71                   }							\
  72                 memcpy (result + result_pos, (data), (len));	\
  73                 result_pos += (len);				\
  74               } while (0)
  75             
  76             #define FMTSPECIAL(ch) \
  77                  (('0' <= (ch) && (ch) <= '9') || (ch) == '.' || (ch) == '-')
  78             
  79             
  80             /*
  81              * Some forward protypes.
  82              */
  83             
  84             static Node *prim_print ___P ((char *prim_name, List *args,
  85 rizwank 1.1 			       Environment *env, char *filename,
  86             			       unsigned int linenum));
  87             
  88             
  89             /*
  90              * Static functions.
  91              */
  92             
  93             static Node *
  94             match_arg (prim_name, type, argp, env, filename, linenum)
  95                  char *prim_name;
  96                  NodeType type;
  97                  ListItem **argp;
  98                  Environment *env;
  99                  char *filename;
 100                  unsigned int linenum;
 101             {
 102               ListItem *arg = *argp;
 103               Node *n;
 104             
 105               NEED_ARG ();
 106 rizwank 1.1   n = eval_expr ((Expr *) arg->data, env);
 107               if (type != nVOID && n->type != type)
 108                 {
 109                   fprintf (stderr, _("%s:%d: %s: illegal argument type\n"),
 110             	       filename, linenum, prim_name);
 111                   exit (1);
 112                 }
 113               *argp = arg->next;
 114             
 115               return n;
 116             }
 117             
 118             /* Primitives. */
 119             
 120             DEFUN (prim_call)
 121             {
 122               ListItem *arg = args->head;
 123               Expr *e;
 124               char *cp;
 125             
 126               e = (Expr *) arg->data;
 127 rizwank 1.1   if (e->type != eSYMBOL)
 128                 {
 129                   fprintf (stderr, _("%s:%d: %s: illegal argument type\n"),
 130             	       filename, linenum, prim_name);
 131                   exit (1);
 132                 }
 133               cp = e->u.node->u.sym;
 134             
 135               arg = arg->next;
 136               LAST_ARG ();
 137             
 138               return execute_state (cp);
 139             }
 140             
 141             DEFUN (prim_calln)
 142             {
 143               ListItem *arg = args->head;
 144               Node *n;
 145               char *cp;
 146             
 147               n = MATCH_ARG (nSTRING);
 148 rizwank 1.1   LAST_ARG ();
 149             
 150               cp = xmalloc (n->u.str.len + 1);
 151               memcpy (cp, n->u.str.data, n->u.str.len);
 152               cp[n->u.str.len] = '\0';
 153             
 154               node_free (n);
 155               n = execute_state (cp);
 156               xfree (cp);
 157             
 158               return n;
 159             }
 160             
 161             
 162             DEFUN (prim_check_namerules)
 163             {
 164               ListItem *arg = args->head;
 165               ListItem *i;
 166               Cons *c;
 167               Node *n;
 168             
 169 rizwank 1.1   LAST_ARG ();
 170             
 171               if (start_state)
 172                 goto return_false;
 173             
 174               for (i = namerules->head; i; i = i->next)
 175                 {
 176                   c = (Cons *) i->data;
 177                   n = (Node *) c->car;
 178             
 179                   if (re_search (REGEXP (n), current_fname, strlen (current_fname),
 180             		     0, strlen (current_fname), NULL) >= 0)
 181             	{
 182             	  /* This is it. */
 183             	  n = (Node *) c->cdr;
 184             
 185             	  start_state = n->u.sym;
 186             
 187             	  n = node_alloc (nINTEGER);
 188             	  n->u.integer = 1;
 189             	  return n;
 190 rizwank 1.1 	}
 191                 }
 192             
 193             return_false:
 194             
 195               n = node_alloc (nINTEGER);
 196               n->u.integer = 0;
 197             
 198               return n;
 199             }
 200             
 201             
 202             DEFUN (prim_check_startrules)
 203             {
 204               ListItem *arg = args->head;
 205               ListItem *i;
 206               Cons *c;
 207               Node *n;
 208             
 209               LAST_ARG ();
 210             
 211 rizwank 1.1   if (start_state)
 212                 goto return_false;
 213             
 214               for (i = startrules->head; i; i = i->next)
 215                 {
 216                   c = (Cons *) i->data;
 217                   n = (Node *) c->car;
 218             
 219                   if (re_search (REGEXP (n), inbuf, data_in_buffer,
 220             		     0, data_in_buffer, NULL) >= 0)
 221             	{
 222             	  /* This is it. */
 223             	  n = (Node *) c->cdr;
 224             
 225             	  start_state = n->u.sym;
 226             
 227             	  n = node_alloc (nINTEGER);
 228             	  n->u.integer = 1;
 229             	  return n;
 230             	}
 231                 }
 232 rizwank 1.1 
 233             return_false:
 234             
 235               n = node_alloc (nINTEGER);
 236               n->u.integer = 0;
 237             
 238               return n;
 239             }
 240             
 241             
 242             DEFUN (prim_concat)
 243             {
 244               ListItem *arg = args->head;
 245               Node *n;
 246               int len = 0;
 247               char *data = NULL;
 248             
 249               NEED_ARG ();
 250               for (; arg; arg = arg->next)
 251                 {
 252                   n = eval_expr ((Expr *) arg->data, env);
 253 rizwank 1.1       if (n->type != nSTRING)
 254             	{
 255             	  fprintf (stderr, _("%s:%d: %s: illegal argument type\n"),
 256             		   filename, linenum, prim_name);
 257             	  exit (1);
 258             	}
 259             
 260                   if (n->u.str.len > 0)
 261             	{
 262             	  data = (char *) xrealloc (data, len + n->u.str.len);
 263             	  memcpy (data + len, n->u.str.data, n->u.str.len);
 264             	  len += n->u.str.len;
 265             	}
 266                   node_free (n);
 267                 }
 268             
 269               n = node_alloc (nSTRING);
 270               n->u.str.data = data;
 271               n->u.str.len = len;
 272             
 273               return n;
 274 rizwank 1.1 }
 275             
 276             
 277             DEFUN (prim_float)
 278             {
 279               ListItem *arg = args->head;
 280               Node *n, *r;
 281               char buf[512];
 282             
 283               n = MATCH_ARG (nVOID);
 284               LAST_ARG ();
 285             
 286               r = node_alloc (nREAL);
 287             
 288               switch (n->type)
 289                 {
 290                 case nVOID:
 291                 case nREGEXP:
 292                 case nSYMBOL:
 293                   r->u.real = 0.0;
 294                   break;
 295 rizwank 1.1 
 296                 case nARRAY:
 297                   r->u.real = (double) n->u.array.len;
 298                   break;
 299             
 300                 case nSTRING:
 301                   if (n->u.str.len > sizeof (buf) - 1)
 302             	r->u.real = 0.0;
 303                   else
 304             	{
 305             	  memcpy (buf, n->u.str.data, n->u.str.len);
 306             	  buf[n->u.str.len] = '\0';
 307             	  r->u.real = atof (buf);
 308             	}
 309                   break;
 310             
 311                 case nINTEGER:
 312                   r->u.real = (double) n->u.integer;
 313                   break;
 314             
 315                 case nREAL:
 316 rizwank 1.1       r->u.real = n->u.real;
 317                   break;
 318                 }
 319             
 320               node_free (n);
 321               return r;
 322             }
 323             
 324             
 325             DEFUN (prim_getenv)
 326             {
 327               ListItem *arg = args->head;
 328               Node *var, *n;
 329               char *key;
 330               char *cp;
 331             
 332               var = MATCH_ARG (nSTRING);
 333               LAST_ARG ();
 334             
 335               key = (char *) xcalloc (1, var->u.str.len + 1);
 336               memcpy (key, var->u.str.data, var->u.str.len);
 337 rizwank 1.1 
 338               cp = getenv (key);
 339             
 340               node_free (var);
 341               xfree (key);
 342             
 343               n = node_alloc (nSTRING);
 344               if (cp == NULL)
 345                 {
 346                   n->u.str.data = (char *) xmalloc (1);
 347                   n->u.str.len = 0;
 348                 }
 349               else
 350                 {
 351                   n->u.str.data = xstrdup (cp);
 352                   n->u.str.len = strlen (cp);
 353                 }
 354             
 355               return n;
 356             }
 357             
 358 rizwank 1.1 
 359             DEFUN (prim_int)
 360             {
 361               ListItem *arg = args->head;
 362               Node *n, *r;
 363               char buf[512];
 364             
 365               n = MATCH_ARG (nVOID);
 366               LAST_ARG ();
 367             
 368               r = node_alloc (nINTEGER);
 369             
 370               switch (n->type)
 371                 {
 372                 case nVOID:
 373                 case nREGEXP:
 374                 case nSYMBOL:
 375                   r->u.integer = 0;
 376                   break;
 377             
 378                 case nARRAY:
 379 rizwank 1.1       r->u.integer = n->u.array.len;
 380                   break;
 381             
 382                 case nSTRING:
 383                   if (n->u.str.len > sizeof (buf) - 1)
 384             	r->u.integer = 0;
 385                   else
 386             	{
 387             	  memcpy (buf, n->u.str.data, n->u.str.len);
 388             	  buf[n->u.str.len] = '\0';
 389             	  r->u.integer = atoi (buf);
 390             	}
 391                   break;
 392             
 393                 case nINTEGER:
 394                   r->u.integer = n->u.integer;
 395                   break;
 396             
 397                 case nREAL:
 398                   r->u.integer = (int) n->u.real;
 399                   break;
 400 rizwank 1.1     }
 401             
 402               node_free (n);
 403               return r;
 404             }
 405             
 406             
 407             DEFUN (prim_length)
 408             {
 409               ListItem *arg = args->head;
 410               Node *n;
 411               int result = 0;
 412             
 413               NEED_ARG ();
 414               for (; arg; arg = arg->next)
 415                 {
 416                   n = eval_expr ((Expr *) arg->data, env);
 417                   switch (n->type)
 418             	{
 419             	case nSTRING:
 420             	  result += n->u.str.len;
 421 rizwank 1.1 	  break;
 422             
 423             	case nARRAY:
 424             	  result += n->u.array.len;
 425             	  break;
 426             
 427             	default:
 428             	  fprintf (stderr, _("%s:%d: %s: illegal argument type\n"),
 429             		   filename, linenum, prim_name);
 430             	  exit (1);
 431             	  break;
 432             	}
 433                   node_free (n);
 434                 }
 435             
 436               n = node_alloc (nINTEGER);
 437               n->u.integer = result;
 438             
 439               return n;
 440             }
 441             
 442 rizwank 1.1 
 443             DEFUN (prim_list)
 444             {
 445               ListItem *arg = args->head;
 446               unsigned int len;
 447               Node *n;
 448             
 449               /* Count list length. */
 450               for (len = 0; arg; len++, arg = arg->next)
 451                 ;
 452               arg = args->head;
 453             
 454               /* Create list node. */
 455               n = node_alloc (nARRAY);
 456               n->u.array.array = (Node **) xcalloc (len + 1, sizeof (Node *));
 457               n->u.array.allocated = len + 1;
 458               n->u.array.len = len;
 459             
 460               /* Fill it up. */
 461               for (len = 0; arg; len++, arg = arg->next)
 462                 n->u.array.array[len] = eval_expr ((Expr *) arg->data, env);
 463 rizwank 1.1 
 464               return n;
 465             }
 466             
 467             
 468             DEFUN (prim_panic)
 469             {
 470               fprintf (stderr, _("%s: panic: "), program);
 471               ofp = stderr;
 472               prim_print (prim_name, args, env, filename, linenum);
 473               fprintf (stderr, "\n");
 474               exit (1);
 475             
 476               /* NOTREACHED */
 477               return nvoid;
 478             }
 479             
 480             
 481             DEFUN (prim_prereq)
 482             {
 483               ListItem *arg = args->head;
 484 rizwank 1.1   Node *s;
 485               int over[3];
 486               int rver[3];
 487               char *cp;
 488               int i;
 489             
 490               s = MATCH_ARG (nSTRING);
 491               LAST_ARG ();
 492             
 493               /* Our version. */
 494               sscanf (VERSION, "%d.%d.%d", &over[0], &over[1], &over[2]);
 495             
 496               /* Required version. */
 497             
 498               cp = (char *) xcalloc (1, s->u.str.len + 1);
 499               memcpy (cp, s->u.str.data, s->u.str.len);
 500             
 501               if (sscanf (cp, "%d.%d.%d", &rver[0], &rver[1], &rver[2]) != 3)
 502                 {
 503                   fprintf (stderr,
 504             	       _("%s:%d: %s: malformed version string `%s'\n"),
 505 rizwank 1.1 	       filename, linenum, prim_name, cp);
 506                   exit (1);
 507                 }
 508             
 509               /* Check version. */
 510               for (i = 0; i < 3; i++)
 511                 {
 512                   if (over[i] > rver[i])
 513             	/* Ok, our version is bigger. */
 514             	break;
 515                   if (over[i] < rver[i])
 516             	{
 517             	  /* Fail, our version is too small. */
 518             	  fprintf (stderr,
 519             		   _("%s: FATAL ERROR: States version %s or higher is required for this script\n"),
 520             		   program, cp);
 521             	  exit (1);
 522             	}
 523                 }
 524             
 525               /* Our version is higher or equal to the required one. */
 526 rizwank 1.1   xfree (cp);
 527             
 528               return nvoid;
 529             }
 530             
 531             
 532             static void
 533             print_node (n)
 534                  Node *n;
 535             {
 536               unsigned int i;
 537             
 538               switch (n->type)
 539                 {
 540                 case nVOID:
 541                   break;
 542             
 543                 case nSTRING:
 544                   fwrite (n->u.str.data, n->u.str.len, 1, ofp);
 545                   break;
 546             
 547 rizwank 1.1     case nREGEXP:
 548                   fputc ('/', ofp);
 549                   fwrite (n->u.re.data, n->u.re.len, 1, ofp);
 550                   fputc ('/', ofp);
 551                   break;
 552             
 553                 case nINTEGER:
 554                   fprintf (ofp, "%d", n->u.integer);
 555                   break;
 556             
 557                 case nREAL:
 558                   fprintf (ofp, "%f", n->u.real);
 559                   break;
 560             
 561                 case nSYMBOL:
 562                   fprintf (ofp, "%s", n->u.sym);
 563                   break;
 564             
 565                 case nARRAY:
 566                   for (i = 0; i < n->u.array.len; i++)
 567             	{
 568 rizwank 1.1 	  print_node (n->u.array.array[i]);
 569             	  if (i + 1 < n->u.array.len)
 570             	    fprintf (ofp, " ");
 571             	}
 572                 }
 573             }
 574             
 575             
 576             DEFUN (prim_print)
 577             {
 578               ListItem *arg = args->head;
 579               Node *n;
 580             
 581               NEED_ARG ();
 582               for (; arg; arg = arg->next)
 583                 {
 584                   n = eval_expr ((Expr *) arg->data, env);
 585                   print_node (n);
 586                   node_free (n);
 587                 }
 588             
 589 rizwank 1.1   return nvoid;
 590             }
 591             
 592             
 593             DEFUN (prim_range)
 594             {
 595               ListItem *arg = args->head;
 596               Node *from, *start, *end, *n;
 597               int i;
 598             
 599               NEED_ARG ();
 600               from = eval_expr ((Expr *) arg->data, env);
 601               arg = arg->next;
 602             
 603               start = MATCH_ARG (nINTEGER);
 604               end = MATCH_ARG (nINTEGER);
 605               LAST_ARG ();
 606             
 607               if (start->u.integer > end->u.integer)
 608                 {
 609                   fprintf (stderr,
 610 rizwank 1.1 	       _("%s:%d: %s: start offset is bigger than end offset\n"),
 611             	       filename, linenum, prim_name);
 612                   exit (1);
 613                 }
 614             
 615               if (from->type == nSTRING)
 616                 {
 617                   if (end->u.integer > from->u.str.len)
 618             	{
 619             	  fprintf (stderr, _("%s:%d: %s: offset out of range\n"),
 620             		   filename, linenum, prim_name);
 621             	  exit (1);
 622             	}
 623             
 624                   n = node_alloc (nSTRING);
 625                   n->u.str.len = end->u.integer - start->u.integer;
 626                   /* +1 to avoid zero allocation */
 627                   n->u.str.data = (char *) xmalloc (n->u.str.len + 1);
 628                   memcpy (n->u.str.data, from->u.str.data + start->u.integer,
 629             	      n->u.str.len);
 630                 }
 631 rizwank 1.1   else if (from->type == nARRAY)
 632                 {
 633                   if (end->u.integer > from->u.array.len)
 634             	{
 635             	  fprintf (stderr, _("%s:%d: %s: offset out of range\n"),
 636             		   filename, linenum, prim_name);
 637             	  exit (1);
 638             	}
 639             
 640                   n = node_alloc (nARRAY);
 641                   n->u.array.len = end->u.integer - start->u.integer;
 642                   /* +1 to avoid zero allocation */
 643                   n->u.array.allocated = n->u.array.len + 1;
 644                   n->u.array.array = (Node **) xcalloc (n->u.array.allocated,
 645             					    sizeof (Node *));
 646             
 647                   for (i = 0; i < n->u.array.len; i++)
 648             	n->u.array.array[i]
 649             	  = node_copy (from->u.array.array[i + start->u.integer]);
 650                 }
 651               else
 652 rizwank 1.1     {
 653                   fprintf (stderr, _("%s:%d: %s: illegal argument\n"),
 654             	       filename, linenum, prim_name);
 655                   exit (1);
 656                 }
 657             
 658               node_free (from);
 659               node_free (start);
 660               node_free (end);
 661             
 662               return n;
 663             }
 664             
 665             
 666             DEFUN (prim_regexp)
 667             {
 668               ListItem *arg = args->head;
 669               Node *str, *n;
 670             
 671               str = MATCH_ARG (nSTRING);
 672               LAST_ARG ();
 673 rizwank 1.1 
 674               /* Create a new REGEXP node. */
 675             
 676               n = node_alloc (nREGEXP);
 677               n->u.re.data = xmalloc (str->u.str.len + 1);
 678               n->u.re.len = str->u.str.len;
 679               memcpy (n->u.re.data, str->u.str.data, str->u.str.len);
 680               n->u.re.data[str->u.str.len] = '\0';
 681             
 682               return n;
 683             }
 684             
 685             
 686             DEFUN (prim_regexp_syntax)
 687             {
 688               ListItem *arg = args->head;
 689               Node *ch, *st;
 690               char syntax;
 691             
 692               ch = MATCH_ARG (nINTEGER);
 693               st = MATCH_ARG (nINTEGER);
 694 rizwank 1.1   LAST_ARG ();
 695             
 696               syntax = (char) st->u.integer;
 697               if (syntax != 'w' && syntax != ' ')
 698                 {
 699                   fprintf (stderr,
 700             	       _("%s:%d: %s: illegal regexp character syntax: %c\n"),
 701             	       filename, linenum, prim_name, syntax);
 702                   exit (1);
 703                 }
 704             
 705               re_set_character_syntax ((unsigned char) ch->u.integer, syntax);
 706             
 707               return nvoid;
 708             }
 709             
 710             
 711             DEFUN (prim_regmatch)
 712             {
 713               ListItem *arg = args->head;
 714               Node *str, *re, *n;
 715 rizwank 1.1   static struct re_registers matches = {0, NULL, NULL};
 716               static Node *current_match_node = NULL;
 717               int i;
 718             
 719               str = MATCH_ARG (nSTRING);
 720               re = MATCH_ARG (nREGEXP);
 721               LAST_ARG ();
 722             
 723               /* Search for match. */
 724               i = re_search (REGEXP (re), str->u.str.data, str->u.str.len,
 725             		 0, str->u.str.len, &matches);
 726             
 727               if (i < 0)
 728                 {
 729                   current_match = NULL;
 730                   node_free (str);
 731                 }
 732               else
 733                 {
 734                   node_free (current_match_node);
 735                   current_match_node = str;
 736 rizwank 1.1 
 737                   current_match = &matches;
 738                   current_match_buf = str->u.str.data;
 739                 }
 740               node_free (re);
 741             
 742               n = node_alloc (nINTEGER);
 743               n->u.integer = (i >= 0);
 744             
 745               return n;
 746             }
 747             
 748             
 749             /*
 750              * Common regular expression substituter for regsub and regsuball.
 751              */
 752             
 753             Node *
 754             do_regsubsts (str, re, subst, allp)
 755                  Node *str;
 756                  Node *re;
 757 rizwank 1.1      Node *subst;
 758                  int allp;
 759             {
 760               int i, pos, j;
 761               static struct re_registers matches = {0, NULL, NULL};
 762               static char *result = NULL;
 763               static unsigned int result_len = 0;
 764               unsigned int result_pos = 0;
 765               int num_matches = 0;
 766               int do_expansions_in_substs = 0;
 767             
 768               /* Do we have to do expansions in the substitution string. */
 769               for (i = 0; i < subst->u.str.len; i++)
 770                 if (subst->u.str.data[i] == '$')
 771                   {
 772             	do_expansions_in_substs = 1;
 773             	break;
 774                   }
 775             
 776               pos = 0;
 777               while (1)
 778 rizwank 1.1     {
 779                   /* Search for match. */
 780                   i = re_search (REGEXP (re), str->u.str.data, str->u.str.len,
 781             		     pos, str->u.str.len - pos, &matches);
 782                   if (i < 0)
 783             	goto out;
 784             
 785                   num_matches++;
 786             
 787                   /* Everything before match. */
 788                   APPEND (str->u.str.data + pos, matches.start[0] - pos);
 789             
 790                   /* Append match. */
 791                   if (!do_expansions_in_substs)
 792             	APPEND (subst->u.str.data, subst->u.str.len);
 793                   else
 794             	{
 795             	  /* Must process substitution string. */
 796             	  for (i = 0; i < subst->u.str.len; i++)
 797             	    if (subst->u.str.data[i] == '$' && i + 1 < subst->u.str.len)
 798             	      {
 799 rizwank 1.1 		i++;
 800             		switch (subst->u.str.data[i])
 801             		  {
 802             		  case '$':
 803             		    APPEND ("$", 1);
 804             		    break;
 805             
 806             		  case '0':
 807             		  case '1':
 808             		  case '2':
 809             		  case '3':
 810             		  case '4':
 811             		  case '5':
 812             		  case '6':
 813             		  case '7':
 814             		  case '8':
 815             		  case '9':
 816             		    j = subst->u.str.data[i] - '0';
 817             		    if (matches.start[j] >= 0)
 818             		      APPEND (str->u.str.data + matches.start[j],
 819             			      matches.end[j] - matches.start[j]);
 820 rizwank 1.1 		    break;
 821             
 822             		  default:
 823             		    /* Illegal substitution, just pass it through. */
 824             		    APPEND ("$", 1);
 825             		    APPEND (subst->u.str.data + i, 1);
 826             		    break;
 827             		  }
 828             	      }
 829             	    else
 830             	      APPEND (subst->u.str.data + i, 1);
 831             	}
 832             
 833                   /* Update pos. */
 834                   pos = matches.end[0];
 835             
 836                   if (!allp)
 837             	break;
 838                 }
 839             
 840             out:
 841 rizwank 1.1   if (num_matches == 0)
 842                 {
 843                   /* No matches, just return our original string. */
 844                   node_free (re);
 845                   node_free (subst);
 846                   return str;
 847                 }
 848             
 849               APPEND (str->u.str.data + pos, str->u.str.len - pos);
 850             
 851               /* Create result node. */
 852               node_free (str);
 853               node_free (re);
 854               node_free (subst);
 855             
 856               str = node_alloc (nSTRING);
 857               str->u.str.len = result_pos;
 858               str->u.str.data = xmalloc (result_pos);
 859               memcpy (str->u.str.data, result, result_pos);
 860             
 861               return str;
 862 rizwank 1.1 }
 863             
 864             
 865             DEFUN (prim_regsub)
 866             {
 867               ListItem *arg = args->head;
 868               Node *str, *re, *subst;
 869             
 870               str = MATCH_ARG (nSTRING);
 871               re = MATCH_ARG (nREGEXP);
 872               subst = MATCH_ARG (nSTRING);
 873               LAST_ARG ();
 874             
 875               return do_regsubsts (str, re, subst, 0);
 876             }
 877             
 878             
 879             DEFUN (prim_regsuball)
 880             {
 881               ListItem *arg = args->head;
 882               Node *str, *re, *subst;
 883 rizwank 1.1 
 884               str = MATCH_ARG (nSTRING);
 885               re = MATCH_ARG (nREGEXP);
 886               subst = MATCH_ARG (nSTRING);
 887               LAST_ARG ();
 888             
 889               return do_regsubsts (str, re, subst, 1);
 890             }
 891             
 892             
 893             DEFUN (prim_require_state)
 894             {
 895               ListItem *arg = args->head;
 896               Expr *e;
 897               char *cp;
 898               State *state;
 899             
 900               e = (Expr *) arg->data;
 901               if (e->type != eSYMBOL)
 902                 {
 903                   fprintf (stderr, _("%s:%d: %s: illegal argument type\n"),
 904 rizwank 1.1 	       filename, linenum, prim_name);
 905                   exit (1);
 906                 }
 907               cp = e->u.node->u.sym;
 908             
 909               arg = arg->next;
 910               LAST_ARG ();
 911             
 912               state = lookup_state (cp);
 913               if (state == NULL)
 914                 {
 915                   fprintf (stderr, _("%s:%d: %s: couldn't define state `%s'\n"),
 916             	       filename, linenum, prim_name, cp);
 917                   exit (1);
 918                 }
 919             
 920               return nvoid;
 921             }
 922             
 923             
 924             DEFUN (prim_split)
 925 rizwank 1.1 {
 926               ListItem *arg = args->head;
 927               Node *re, *str, *n, *n2;
 928               int pos, i;
 929             
 930               re = MATCH_ARG (nREGEXP);
 931               str = MATCH_ARG (nSTRING);
 932               LAST_ARG ();
 933             
 934               /* Create a new array node. */
 935               n = node_alloc (nARRAY);
 936               n->u.array.allocated = 100;
 937               n->u.array.array = (Node **) xcalloc (n->u.array.allocated, sizeof (Node *));
 938             
 939               for (pos = 0; pos < str->u.str.len;)
 940                 {
 941                   i = re_search (REGEXP (re), str->u.str.data, str->u.str.len,
 942             		     pos, str->u.str.len - pos, &re->u.re.matches);
 943                   if (i < 0)
 944             	/* No more matches. */
 945             	break;
 946 rizwank 1.1 
 947                   /* Append the string before the first match. */
 948                   n2 = node_alloc (nSTRING);
 949                   n2->u.str.len = i - pos;
 950                   n2->u.str.data = (char *) xmalloc (n2->u.str.len + 1);
 951                   memcpy (n2->u.str.data, str->u.str.data + pos, n2->u.str.len);
 952                   pos = re->u.re.matches.end[0];
 953             
 954                   /*
 955                    * Check that at least one item fits after us (no need to check
 956                    * when appending the last item).
 957                    */
 958                   if (n->u.array.len + 1 >= n->u.array.allocated)
 959             	{
 960             	  n->u.array.allocated += 100;
 961             	  n->u.array.array = (Node **) xrealloc (n->u.array.array,
 962             						 n->u.array.allocated
 963             						 * sizeof (Node *));
 964             	}
 965                   n->u.array.array[n->u.array.len++] = n2;
 966                 }
 967 rizwank 1.1 
 968               /* Append all the remaining data. */
 969               n2 = node_alloc (nSTRING);
 970               n2->u.str.len = str->u.str.len - pos;
 971               n2->u.str.data = (char *) xmalloc (n2->u.str.len + 1);
 972               memcpy (n2->u.str.data, str->u.str.data + pos, n2->u.str.len);
 973             
 974               n->u.array.array[n->u.array.len++] = n2;
 975             
 976               return n;
 977             }
 978             
 979             
 980             DEFUN (prim_sprintf)
 981             {
 982               ListItem *arg = args->head;
 983               Node *fmt, *n;
 984               char buf[512];
 985               char ifmt[256];
 986               char ifmtopts[256];
 987               char *result = NULL;
 988 rizwank 1.1   unsigned int result_pos = 0;
 989               unsigned int result_len = 0;
 990               int i, j;
 991               int argument_count = 0;
 992               char *cp;
 993             
 994               fmt = MATCH_ARG (nSTRING);
 995               cp = fmt->u.str.data;
 996             
 997               /* Process format string and match arguments. */
 998               for (i = 0; i < fmt->u.str.len; i++)
 999                 {
1000                   if (cp[i] == '%' && (i + 1 >= fmt->u.str.len || cp[i + 1] == '%'))
1001             	{
1002             	  i++;
1003             	  APPEND (cp + i, 1);
1004             	}
1005                   else if (cp[i] == '%')
1006             	{
1007             	  argument_count++;
1008             
1009 rizwank 1.1 	  if (arg == NULL)
1010             	    {
1011             	      fprintf (stderr,
1012             		       _("%s: primitive `%s': too few arguments for format\n"),
1013             		       program, prim_name);
1014             	      exit (1);
1015             	    }
1016             	  n = eval_expr ((Expr *) arg->data, env);
1017             	  arg = arg->next;
1018             
1019             	  for (i++, j = 0; i < fmt->u.str.len && FMTSPECIAL (cp[i]); i++, j++)
1020             	    ifmtopts[j] = cp[i];
1021             	  ifmtopts[j] = '\0';
1022             
1023             	  if (i >= fmt->u.str.len)
1024             	    {
1025             	      APPEND ("%", 1);
1026             	      APPEND (ifmtopts, j);
1027             	      continue;
1028             	    }
1029             
1030 rizwank 1.1 	  /* Field type. */
1031             	  switch (cp[i])
1032             	    {
1033             	    case 'x':
1034             	    case 'X':
1035             	    case 'd':
1036             	      if (n->type != nINTEGER)
1037             		{
1038             		no_match:
1039             		  fprintf (stderr,
1040             			   _("%s:%d: %s: argument %d doesn't match format\n"),
1041             			   filename, linenum, prim_name, argument_count);
1042             		  exit (1);
1043             		}
1044             	      sprintf (ifmt, "%%%s%c", ifmtopts, cp[i]);
1045             	      sprintf (buf, ifmt, n->u.integer);
1046             
1047             	      APPEND (buf, strlen (buf));
1048             	      break;
1049             
1050             	    case 'c':
1051 rizwank 1.1 	      if (n->type != nINTEGER)
1052             		goto no_match;
1053             
1054             	      sprintf (ifmt, "%%%s%c", ifmtopts, cp[i]);
1055             	      sprintf (buf, ifmt, n->u.integer);
1056             
1057             	      APPEND (buf, strlen (buf));
1058             	      break;
1059             
1060             	    case 'f':
1061             	    case 'g':
1062             	    case 'e':
1063             	    case 'E':
1064             	      if (n->type != nREAL)
1065             		goto no_match;
1066             
1067             	      sprintf (ifmt, "%%%s%c", ifmtopts, cp[i]);
1068             	      sprintf (buf, ifmt, n->u.real);
1069             
1070             	      APPEND (buf, strlen (buf));
1071             	      break;
1072 rizwank 1.1 
1073             	    case 's':
1074             	      if (n->type != nSTRING)
1075             		goto no_match;
1076             
1077             	      if (ifmtopts[0] != '\0')
1078             		{
1079             		  fprintf (stderr,
1080             			   _("%s:%d: %s: no extra options can be specified for %%s\n"),
1081             			   filename, linenum, prim_name);
1082             		  exit (1);
1083             		}
1084             	      APPEND (n->u.str.data, n->u.str.len);
1085             	      break;
1086             
1087             	    default:
1088             	      fprintf (stderr,
1089             		       _("%s:%d: %s: illegal type specifier `%c'\n"),
1090             		       filename, linenum, prim_name, cp[i]);
1091             	      exit (1);
1092             	      break;
1093 rizwank 1.1 	    }
1094             	}
1095                   else
1096             	APPEND (cp + i, 1);
1097                 }
1098             
1099               node_free (fmt);
1100             
1101               n = node_alloc (nSTRING);
1102               n->u.str.len = result_pos;
1103               n->u.str.data = result;
1104             
1105               return n;
1106             }
1107             
1108             
1109             DEFUN (prim_strcmp)
1110             {
1111               ListItem *arg = args->head;
1112               Node *s1, *s2;
1113               Node *n;
1114 rizwank 1.1   int i, result;
1115               char *cp1, *cp2;
1116             
1117               s1 = MATCH_ARG (nSTRING);
1118               s2 = MATCH_ARG (nSTRING);
1119               LAST_ARG ();
1120             
1121               cp1 = s1->u.str.data;
1122               cp2 = s2->u.str.data;
1123             
1124               for (i = 0; i < s1->u.str.len && i < s2->u.str.len; i++)
1125                 {
1126                   if (cp1[i] < cp2[i])
1127             	{
1128             	  result = -1;
1129             	  goto out;
1130             	}
1131                   if (cp1[i] > cp2[i])
1132             	{
1133             	  result = 1;
1134             	  goto out;
1135 rizwank 1.1 	}
1136                 }
1137               /* Strings are so far equal, check lengths. */
1138               if (s1->u.str.len < s2->u.str.len)
1139                 result = -1;
1140               else if (s1->u.str.len > s2->u.str.len)
1141                 result = 1;
1142               else
1143                 result = 0;
1144             
1145             out:
1146               node_free (s1);
1147               node_free (s2);
1148               n = node_alloc (nINTEGER);
1149               n->u.integer = result;
1150             
1151               return n;
1152             }
1153             
1154             
1155             DEFUN (prim_string)
1156 rizwank 1.1 {
1157               ListItem *arg = args->head;
1158               Node *n, *r;
1159               char buf[512];
1160             
1161               n = MATCH_ARG (nVOID);
1162               LAST_ARG ();
1163             
1164               r = node_alloc (nSTRING);
1165             
1166               switch (n->type)
1167                 {
1168                 case nVOID:
1169                 case nREGEXP:
1170                 case nARRAY:
1171                   r->u.str.data = (char *) xcalloc (1, 1);
1172                   r->u.str.len = 0;
1173                   break;
1174             
1175                 case nSYMBOL:
1176                   r->u.str.len = strlen (n->u.sym);
1177 rizwank 1.1       r->u.str.data = (char *) xmalloc (r->u.str.len);
1178                   memcpy (r->u.str.data, n->u.sym, r->u.str.len);
1179                   break;
1180             
1181                 case nSTRING:
1182                   r->u.str.len = n->u.str.len;
1183                   r->u.str.data = (char *) xmalloc (n->u.str.len);
1184                   memcpy (r->u.str.data, n->u.str.data, n->u.str.len);
1185                   break;
1186             
1187                 case nINTEGER:
1188                   sprintf (buf, "%d", n->u.integer);
1189                   r->u.str.len = strlen (buf);
1190                   r->u.str.data = (char *) xmalloc (r->u.str.len);
1191                   memcpy (r->u.str.data, buf, r->u.str.len);
1192                   break;
1193             
1194                 case nREAL:
1195                   sprintf (buf, "%f", n->u.real);
1196                   r->u.str.len = strlen (buf);
1197                   r->u.str.data = (char *) xmalloc (r->u.str.len);
1198 rizwank 1.1       memcpy (r->u.str.data, buf, r->u.str.len);
1199                   break;
1200                 }
1201             
1202               node_free (n);
1203               return r;
1204             }
1205             
1206             
1207             DEFUN (prim_strncmp)
1208             {
1209               ListItem *arg = args->head;
1210               Node *s1, *s2, *len;
1211               Node *n;
1212               int i, result;
1213               char *cp1, *cp2;
1214             
1215               s1 = MATCH_ARG (nSTRING);
1216               s2 = MATCH_ARG (nSTRING);
1217               len = MATCH_ARG (nINTEGER);
1218               LAST_ARG ();
1219 rizwank 1.1 
1220               cp1 = s1->u.str.data;
1221               cp2 = s2->u.str.data;
1222             
1223               for (i = 0; i < s1->u.str.len && i < s2->u.str.len && i < len->u.integer; i++)
1224                 {
1225                   if (cp1[i] < cp2[i])
1226             	{
1227             	  result = -1;
1228             	  goto out;
1229             	}
1230                   if (cp1[i] > cp2[i])
1231             	{
1232             	  result = 1;
1233             	  goto out;
1234             	}
1235                 }
1236             
1237               /* Check the limit length. */
1238               if (i >= len->u.integer)
1239                 {
1240 rizwank 1.1       result = 0;
1241                   goto out;
1242                 }
1243             
1244               /* One or both strings were shorter than limit, check lengths. */
1245               if (s1->u.str.len < s2->u.str.len)
1246                 result = -1;
1247               else if (s1->u.str.len > s2->u.str.len)
1248                 result = 1;
1249               else
1250                 result = 0;
1251             
1252             out:
1253               node_free (s1);
1254               node_free (s2);
1255               node_free (len);
1256               n = node_alloc (nINTEGER);
1257               n->u.integer = result;
1258             
1259               return n;
1260             }
1261 rizwank 1.1 
1262             
1263             DEFUN (prim_substring)
1264             {
1265               ListItem *arg = args->head;
1266               Node *str, *start, *end, *n;
1267             
1268               str = MATCH_ARG (nSTRING);
1269               start = MATCH_ARG (nINTEGER);
1270               end = MATCH_ARG (nINTEGER);
1271               LAST_ARG ();
1272             
1273               if (start->u.integer > end->u.integer)
1274                 {
1275                   fprintf (stderr,
1276             	       _("%s:%d: %s: start offset is bigger than end offset\n"),
1277             	       filename, linenum, prim_name);
1278                   exit (1);
1279                 }
1280               if (end->u.integer > str->u.str.len)
1281                 {
1282 rizwank 1.1       fprintf (stderr, _("%s:%d: %s: offset out of range\n"),
1283             	       filename, linenum, prim_name);
1284                   exit (1);
1285                 }
1286             
1287               n = node_alloc (nSTRING);
1288               n->u.str.len = end->u.integer - start->u.integer;
1289               /* +1 to avoid zero allocation */
1290               n->u.str.data = (char *) xmalloc (n->u.str.len + 1);
1291             
1292               memcpy (n->u.str.data, str->u.str.data + start->u.integer,
1293             	  n->u.str.len);
1294             
1295               node_free (str);
1296               node_free (start);
1297               node_free (end);
1298             
1299               return n;
1300             }
1301             
1302             
1303 rizwank 1.1 DEFUN (prim_system)
1304             {
1305               ListItem *arg = args->head;
1306               Node *str, *n;
1307               char *cmd;
1308               int result;
1309             
1310               str = MATCH_ARG (nSTRING);
1311               LAST_ARG ();
1312             
1313               cmd = (char *) xcalloc (1, str->u.str.len + 1);
1314               memcpy (cmd, str->u.str.data, str->u.str.len);
1315             
1316               result = system (cmd);
1317               xfree (cmd);
1318             
1319               n = node_alloc (nINTEGER);
1320               n->u.integer = result;
1321             
1322               return n;
1323             }
1324 rizwank 1.1 
1325             
1326             /*
1327              * Global functions.
1328              */
1329             
1330             static struct
1331             {
1332               char *name;
1333               Primitive prim;
1334             } prims[] =
1335               {
1336                 {"call", 			prim_call},
1337                 {"calln", 			prim_calln},
1338                 {"check_namerules",		prim_check_namerules},
1339                 {"check_startrules",	prim_check_startrules},
1340                 {"concat",			prim_concat},
1341                 {"float", 			prim_float},
1342                 {"getenv", 			prim_getenv},
1343                 {"int",			prim_int},
1344                 {"length",			prim_length},
1345 rizwank 1.1     {"list", 			prim_list},
1346                 {"panic", 			prim_panic},
1347                 {"prereq", 			prim_prereq},
1348                 {"print", 			prim_print},
1349                 {"range", 			prim_range},
1350                 {"regexp",			prim_regexp},
1351                 {"regexp_syntax",		prim_regexp_syntax},
1352                 {"regmatch",		prim_regmatch},
1353                 {"regsub",			prim_regsub},
1354                 {"regsuball",		prim_regsuball},
1355                 {"require_state",		prim_require_state},
1356                 {"split",			prim_split},
1357                 {"sprintf",			prim_sprintf},
1358                 {"strcmp",			prim_strcmp},
1359                 {"string",			prim_string},
1360                 {"strncmp",			prim_strncmp},
1361                 {"substring",		prim_substring},
1362                 {"system",			prim_system},
1363             
1364                 {NULL, NULL},
1365               };
1366 rizwank 1.1 
1367             void
1368             init_primitives ()
1369             {
1370               void *old;
1371               int i;
1372             
1373               for (i = 0; prims[i].name; i++)
1374                 if (!strhash_put (ns_prims, prims[i].name, strlen (prims[i].name),
1375             		      (void *) prims[i].prim, &old))
1376                   {
1377             	fprintf (stderr, _("%s: out of memory\n"), program);
1378             	exit (1);
1379                   }
1380             }

Rizwan Kassim
Powered by
ViewCVS 0.9.2