rxgen: per-opcode stats
authorDerrick Brashear <shadow@dementix.org>
Sat, 21 Jul 2012 04:17:14 +0000 (00:17 -0400)
committerDerrick Brashear <shadow@dementix.org>
Sun, 22 Jul 2012 12:18:50 +0000 (05:18 -0700)
allow access to per-opcode stats

Change-Id: I17639cf23acac23acfb9cb7dc07a7c5c81d4ff89
Reviewed-on: http://gerrit.openafs.org/7802
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jacob Thebault-Spieker <summatusmentis@gmail.com>
Reviewed-by: Derrick Brashear <shadow@dementix.org>

src/libafsrpc/afsrpc.def
src/rx/rx.c
src/rx/rx.h
src/rx/rx_prototypes.h
src/rxgen/rpc_parse.c
src/rxgen/rpc_parse.h

index 59ad355..3315184 100755 (executable)
@@ -331,6 +331,13 @@ EXPORTS
        rx_HostOf                               @337
         rx_PortOf                               @338
 
+        rx_ClearProcessRPCStats                 @339
+        rx_ClearPeerRPCStats                    @340
+        rx_CopyProcessRPCStats                  @341
+        rx_CopyPeerRPCStats                     @342
+       rx_ReleaseRPCStats                      @343
+        RXAFS_OpCodeIndex                       @344
+
 ; for performance testing
         rx_TSFPQGlobSize                        @2001 DATA
         rx_TSFPQLocalMax                        @2002 DATA
index 79956d4..81dff70 100644 (file)
@@ -8040,9 +8040,34 @@ static int rxi_monitor_processStats = 0;
 
 static int rxi_monitor_peerStats = 0;
 
+
+void
+rxi_ClearRPCOpStat(rx_function_entry_v1_p rpc_stat)
+{
+    rpc_stat->invocations = 0;
+    rpc_stat->bytes_sent = 0;
+    rpc_stat->bytes_rcvd = 0;
+    rpc_stat->queue_time_sum.sec = 0;
+    rpc_stat->queue_time_sum.usec = 0;
+    rpc_stat->queue_time_sum_sqr.sec = 0;
+    rpc_stat->queue_time_sum_sqr.usec = 0;
+    rpc_stat->queue_time_min.sec = 9999999;
+    rpc_stat->queue_time_min.usec = 9999999;
+    rpc_stat->queue_time_max.sec = 0;
+    rpc_stat->queue_time_max.usec = 0;
+    rpc_stat->execution_time_sum.sec = 0;
+    rpc_stat->execution_time_sum.usec = 0;
+    rpc_stat->execution_time_sum_sqr.sec = 0;
+    rpc_stat->execution_time_sum_sqr.usec = 0;
+    rpc_stat->execution_time_min.sec = 9999999;
+    rpc_stat->execution_time_min.usec = 9999999;
+    rpc_stat->execution_time_max.sec = 0;
+    rpc_stat->execution_time_max.usec = 0;
+}
+
 /*!
  * Given all of the information for a particular rpc
- * call, create (if needed) and update the stat totals for the rpc.
+ * call, find or create (if requested) the stat structure for the rpc.
  *
  * @param stats
  *     the queue of stats that will be updated with the new value
@@ -8050,53 +8075,41 @@ static int rxi_monitor_peerStats = 0;
  * @param rxInterface
  *     a unique number that identifies the rpc interface
  *
- * @param currentFunc
- *     the index of the function being invoked
- *
  * @param totalFunc
- *     the total number of functions in this interface
- *
- * @param queueTime
- *     the amount of time this function waited for a thread
- *
- * @param execTime
- *     the amount of time this function invocation took to execute
- *
- * @param bytesSent
- *     the number bytes sent by this invocation
- *
- * @param bytesRcvd
- *     the number bytes received by this invocation
+ *     the total number of functions in this interface. this is only
+ *      required if create is true
  *
  * @param isServer
  *     if true, this invocation was made to a server
  *
  * @param remoteHost
- *     the ip address of the remote host
+ *     the ip address of the remote host. this is only required if create
+ *      and addToPeerList are true
  *
  * @param remotePort
- *     the port of the remote host
+ *     the port of the remote host. this is only required if create
+ *      and addToPeerList are true
  *
  * @param addToPeerList
  *     if != 0, add newly created stat to the global peer list
  *
  * @param counter
  *     if a new stats structure is allocated, the counter will
- *     be updated with the new number of allocated stat structures
+ *     be updated with the new number of allocated stat structures.
+ *      only required if create is true
+ *
+ * @param create
+ *     if no stats structure exists, allocate one
  *
  */
 
-static int
-rxi_AddRpcStat(struct rx_queue *stats, afs_uint32 rxInterface,
-              afs_uint32 currentFunc, afs_uint32 totalFunc,
-              struct clock *queueTime, struct clock *execTime,
-              afs_uint64 bytesSent, afs_uint64 bytesRcvd, int isServer,
-              afs_uint32 remoteHost, afs_uint32 remotePort,
-              int addToPeerList, unsigned int *counter)
+static rx_interface_stat_p
+rxi_FindRpcStat(struct rx_queue *stats, afs_uint32 rxInterface,
+               afs_uint32 totalFunc, int isServer, afs_uint32 remoteHost,
+               afs_uint32 remotePort, int addToPeerList,
+               unsigned int *counter, int create)
 {
-    int rc = 0;
     rx_interface_stat_p rpc_stat, nrpc_stat;
-
     /*
      * See if there's already a structure for this interface
      */
@@ -8107,6 +8120,14 @@ rxi_AddRpcStat(struct rx_queue *stats, afs_uint32 rxInterface,
            break;
     }
 
+    /* if they didn't ask us to create, we're done */
+    if (!create)
+       return rpc_stat;
+
+    /* can't proceed without these */
+    if (!totalFunc || !counter)
+       return NULL;
+
     /*
      * Didn't find a match so allocate a new structure and add it to the
      * queue.
@@ -8123,43 +8144,208 @@ rxi_AddRpcStat(struct rx_queue *stats, afs_uint32 rxInterface,
            totalFunc * sizeof(rx_function_entry_v1_t);
 
        rpc_stat = rxi_Alloc(space);
-       if (rpc_stat == NULL) {
-           rc = 1;
-           goto fail;
-       }
+       if (rpc_stat == NULL)
+           return NULL;
+
        *counter += totalFunc;
        for (i = 0; i < totalFunc; i++) {
+           rxi_ClearRPCOpStat(&(rpc_stat->stats[i]));
            rpc_stat->stats[i].remote_peer = remoteHost;
            rpc_stat->stats[i].remote_port = remotePort;
            rpc_stat->stats[i].remote_is_server = isServer;
            rpc_stat->stats[i].interfaceId = rxInterface;
            rpc_stat->stats[i].func_total = totalFunc;
            rpc_stat->stats[i].func_index = i;
-           rpc_stat->stats[i].invocations = 0;
-           rpc_stat->stats[i].bytes_sent = 0;
-           rpc_stat->stats[i].bytes_rcvd = 0;
-           rpc_stat->stats[i].queue_time_sum.sec = 0;
-           rpc_stat->stats[i].queue_time_sum.usec = 0;
-           rpc_stat->stats[i].queue_time_sum_sqr.sec = 0;
-           rpc_stat->stats[i].queue_time_sum_sqr.usec = 0;
-           rpc_stat->stats[i].queue_time_min.sec = 9999999;
-           rpc_stat->stats[i].queue_time_min.usec = 9999999;
-           rpc_stat->stats[i].queue_time_max.sec = 0;
-           rpc_stat->stats[i].queue_time_max.usec = 0;
-           rpc_stat->stats[i].execution_time_sum.sec = 0;
-           rpc_stat->stats[i].execution_time_sum.usec = 0;
-           rpc_stat->stats[i].execution_time_sum_sqr.sec = 0;
-           rpc_stat->stats[i].execution_time_sum_sqr.usec = 0;
-           rpc_stat->stats[i].execution_time_min.sec = 9999999;
-           rpc_stat->stats[i].execution_time_min.usec = 9999999;
-           rpc_stat->stats[i].execution_time_max.sec = 0;
-           rpc_stat->stats[i].execution_time_max.usec = 0;
        }
        queue_Prepend(stats, rpc_stat);
        if (addToPeerList) {
            queue_Prepend(&peerStats, &rpc_stat->all_peers);
        }
     }
+    return rpc_stat;
+}
+
+void
+rx_ClearProcessRPCStats(afs_int32 rxInterface)
+{
+    rx_interface_stat_p rpc_stat;
+    int totalFunc, i;
+
+    if (rxInterface == -1)
+        return;
+
+    MUTEX_ENTER(&rx_rpc_stats);
+    rpc_stat = rxi_FindRpcStat(&processStats, rxInterface, 0, 0,
+                              0, 0, 0, 0, 0);
+    if (rpc_stat) {
+       totalFunc = rpc_stat->stats[0].func_total;
+       for (i = 0; i < totalFunc; i++)
+           rxi_ClearRPCOpStat(&(rpc_stat->stats[i]));
+    }
+    MUTEX_EXIT(&rx_rpc_stats);
+    return;
+}
+
+void
+rx_ClearPeerRPCStats(afs_int32 rxInterface, afs_uint32 peerHost, afs_uint16 peerPort)
+{
+    rx_interface_stat_p rpc_stat;
+    int totalFunc, i;
+    struct rx_peer * peer;
+
+    if (rxInterface == -1)
+        return;
+
+    peer = rxi_FindPeer(peerHost, peerPort, 0, 0);
+    if (!peer)
+        return;
+
+    MUTEX_ENTER(&rx_rpc_stats);
+    rpc_stat = rxi_FindRpcStat(&peer->rpcStats, rxInterface, 0, 1,
+                              0, 0, 0, 0, 0);
+    if (rpc_stat) {
+       totalFunc = rpc_stat->stats[0].func_total;
+       for (i = 0; i < totalFunc; i++)
+           rxi_ClearRPCOpStat(&(rpc_stat->stats[i]));
+    }
+    MUTEX_EXIT(&rx_rpc_stats);
+    return;
+}
+
+void *
+rx_CopyProcessRPCStats(afs_uint64 op)
+{
+    rx_interface_stat_p rpc_stat;
+    rx_function_entry_v1_p rpcop_stat =
+       rxi_Alloc(sizeof(rx_function_entry_v1_t));
+    int currentFunc = (op & MAX_AFS_UINT32);
+    afs_int32 rxInterface = (op >> 32);
+
+    if (!rxi_monitor_processStats)
+        return NULL;
+
+    if (rxInterface == -1)
+        return NULL;
+
+    MUTEX_ENTER(&rx_rpc_stats);
+    rpc_stat = rxi_FindRpcStat(&processStats, rxInterface, 0, 0,
+                              0, 0, 0, 0, 0);
+    if (rpc_stat)
+       memcpy(rpcop_stat, &(rpc_stat->stats[currentFunc]),
+              sizeof(rx_function_entry_v1_t));
+    MUTEX_EXIT(&rx_rpc_stats);
+    if (!rpc_stat) {
+       rxi_Free(rpcop_stat, sizeof(rx_function_entry_v1_t));
+       return NULL;
+    }
+    return rpcop_stat;
+}
+
+void *
+rx_CopyPeerRPCStats(afs_uint64 op, afs_uint32 peerHost, afs_uint16 peerPort)
+{
+    rx_interface_stat_p rpc_stat;
+    rx_function_entry_v1_p rpcop_stat =
+       rxi_Alloc(sizeof(rx_function_entry_v1_t));
+    int currentFunc = (op & MAX_AFS_UINT32);
+    afs_int32 rxInterface = (op >> 32);
+    struct rx_peer *peer;
+
+    if (!rxi_monitor_peerStats)
+        return NULL;
+
+    if (rxInterface == -1)
+        return NULL;
+
+    peer = rxi_FindPeer(peerHost, peerPort, 0, 0);
+    if (!peer)
+        return NULL;
+
+    MUTEX_ENTER(&rx_rpc_stats);
+    rpc_stat = rxi_FindRpcStat(&peer->rpcStats, rxInterface, 0, 1,
+                              0, 0, 0, 0, 0);
+    if (rpc_stat)
+       memcpy(rpcop_stat, &(rpc_stat->stats[currentFunc]),
+              sizeof(rx_function_entry_v1_t));
+    MUTEX_EXIT(&rx_rpc_stats);
+    if (!rpc_stat) {
+       rxi_Free(rpcop_stat, sizeof(rx_function_entry_v1_t));
+       return NULL;
+    }
+    return rpcop_stat;
+}
+
+void
+rx_ReleaseRPCStats(void *stats)
+{
+    if (stats)
+       rxi_Free(stats, sizeof(rx_function_entry_v1_t));
+}
+
+/*!
+ * Given all of the information for a particular rpc
+ * call, create (if needed) and update the stat totals for the rpc.
+ *
+ * @param stats
+ *     the queue of stats that will be updated with the new value
+ *
+ * @param rxInterface
+ *     a unique number that identifies the rpc interface
+ *
+ * @param currentFunc
+ *     the index of the function being invoked
+ *
+ * @param totalFunc
+ *     the total number of functions in this interface
+ *
+ * @param queueTime
+ *     the amount of time this function waited for a thread
+ *
+ * @param execTime
+ *     the amount of time this function invocation took to execute
+ *
+ * @param bytesSent
+ *     the number bytes sent by this invocation
+ *
+ * @param bytesRcvd
+ *     the number bytes received by this invocation
+ *
+ * @param isServer
+ *     if true, this invocation was made to a server
+ *
+ * @param remoteHost
+ *     the ip address of the remote host
+ *
+ * @param remotePort
+ *     the port of the remote host
+ *
+ * @param addToPeerList
+ *     if != 0, add newly created stat to the global peer list
+ *
+ * @param counter
+ *     if a new stats structure is allocated, the counter will
+ *     be updated with the new number of allocated stat structures
+ *
+ */
+
+static int
+rxi_AddRpcStat(struct rx_queue *stats, afs_uint32 rxInterface,
+              afs_uint32 currentFunc, afs_uint32 totalFunc,
+              struct clock *queueTime, struct clock *execTime,
+              afs_uint64 bytesSent, afs_uint64 bytesRcvd, int isServer,
+              afs_uint32 remoteHost, afs_uint32 remotePort,
+              int addToPeerList, unsigned int *counter)
+{
+    int rc = 0;
+    rx_interface_stat_p rpc_stat;
+
+    rpc_stat = rxi_FindRpcStat(stats, rxInterface, totalFunc, isServer,
+                              remoteHost, remotePort, addToPeerList, counter,
+                              1);
+    if (!rpc_stat) {
+       rc = -1;
+       goto fail;
+    }
 
     /*
      * Increment the stats for this function
index 74deffc..599935a 100644 (file)
@@ -890,4 +890,105 @@ extern int rx_DumpCalls(FILE *outputFile, char *cookie);
 #include "rx_prototypes.h"
 #endif
 
+static_inline afs_uint32
+RPCOpStat_Peer(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return rpcop_stat->remote_peer;
+}
+
+static_inline afs_uint32
+RPCOpStat_Port(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return rpcop_stat->remote_port;
+}
+
+static_inline afs_uint32
+RPCOpStat_IsServer(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return rpcop_stat->remote_is_server;
+}
+
+static_inline afs_uint32
+RPCOpStat_InterfaceId(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return rpcop_stat->interfaceId;
+}
+
+static_inline afs_uint32
+RPCOpStat_NumFuncs(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return rpcop_stat->func_total;
+}
+
+static_inline afs_uint32
+RPCOpStat_CurFunc(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return rpcop_stat->func_index;
+}
+
+static_inline struct clock *
+RPCOpStat_QTimeSum(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return &(rpcop_stat->queue_time_sum);
+}
+
+static_inline struct clock *
+RPCOpStat_QTimeSumSqr(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return &(rpcop_stat->queue_time_sum_sqr);
+}
+
+static_inline struct clock *
+RPCOpStat_QTimeSumMin(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return &(rpcop_stat->queue_time_min);
+}
+
+static_inline struct clock *
+RPCOpStat_QTimeSumMax(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return &(rpcop_stat->queue_time_max);
+}
+
+static_inline struct clock *
+RPCOpStat_ExecTimeSum(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return &(rpcop_stat->execution_time_sum);
+}
+
+static_inline struct clock *
+RPCOpStat_ExecTimeSumSqr(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return &(rpcop_stat->execution_time_sum_sqr);
+}
+
+static_inline struct clock *
+RPCOpStat_ExecTimeSumMin(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return &(rpcop_stat->execution_time_min);
+}
+
+static_inline struct clock *
+RPCOpStat_ExecTimeSumMax(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return &(rpcop_stat->execution_time_max);
+}
+
+static_inline afs_uint64
+RPCOpStat_NumCalls(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return rpcop_stat->invocations;
+}
+
+static_inline afs_uint64
+RPCOpStat_BytesSent(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return rpcop_stat->bytes_sent;
+}
+
+static_inline afs_uint64
+RPCOpStat_BytesRcvd(void *blob) {
+    rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob;
+    return rpcop_stat->bytes_rcvd;
+}
 #endif /* !KDUMP_RX_LOCK */
index c42fdcb..e533cd1 100644 (file)
@@ -167,6 +167,11 @@ extern void rx_clearProcessRPCStats(afs_uint32 clearFlag);
 extern void rx_clearPeerRPCStats(afs_uint32 clearFlag);
 extern void rx_SetRxStatUserOk(int (*proc) (struct rx_call * call));
 extern int rx_RxStatUserOk(struct rx_call *call);
+extern void rx_ClearProcessRPCStats(afs_int32 rxInterface);
+extern void rx_ClearPeerRPCStats(afs_int32 rxInterface, afs_uint32 peerHost, afs_uint16 peerPort);
+extern void *rx_CopyProcessRPCStats(afs_uint64 op);
+extern void *rx_CopyPeerRPCStats(afs_uint64 op, afs_uint32 peerHost, afs_uint16 peerPort);
+extern void rx_ReleaseRPCStats(void *stats);
 extern afs_int32 rx_SetSecurityConfiguration(struct rx_service *service,
                                             rx_securityConfigVariables type,
                                             void *value);
index 3eff6a3..3132055 100644 (file)
@@ -143,9 +143,12 @@ static void er_ProcDeclExterns_setup(void);
 static void er_ProcProcsArray_setup(void);
 static void er_ProcMainBody_setup(void);
 static void er_HeadofOldStyleProc_setup(void);
+static void er_HeadofOldStyleProc_setup2(void);
 static void er_BodyofOldStyleProc_setup(void);
+static void er_BodyofOldStyleProc_setup2(void);
 static void proc_er_case(definition * defp);
 static void er_TailofOldStyleProc_setup(void);
+static void er_TailofOldStyleProc_setup2(void);
 
 
 
@@ -842,6 +845,7 @@ check_proc(definition * defp, token * tokp, int noname)
            prefix, PackagePrefix[PackageIndex], defp->pc.proc_name);
 
     function_list_index++;
+    defp->statindex = no_of_stat_funcs;
     no_of_stat_funcs_header[PackageIndex]++;
     no_of_stat_funcs++;
     *Proc_listp = NULL;
@@ -1972,6 +1976,9 @@ er_Proc_CodeGeneration(void)
            er_HeadofOldStyleProc_setup();
            er_BodyofOldStyleProc_setup();
            er_TailofOldStyleProc_setup();
+           er_HeadofOldStyleProc_setup2();
+           er_BodyofOldStyleProc_setup2();
+           er_TailofOldStyleProc_setup2();
        } else {
            er_ProcDeclExterns_setup();
            er_ProcProcsArray_setup();
@@ -2056,6 +2063,13 @@ er_ProcMainBody_setup(void)
                PackagePrefix[PackageIndex], PackagePrefix[PackageIndex]);
        f_print(fout, "\treturn opnames%d[op - %sLOWEST_OPCODE];\n}\n",
                PackageIndex, PackagePrefix[PackageIndex]);
+       f_print(fout, "struct %sstats *%sOpCodeStats(int op)\n{\n",
+               PackagePrefix[PackageIndex], PackagePrefix[PackageIndex]);
+       f_print(fout, "\tif (op < %sLOWEST_OPCODE || op > %sHIGHEST_OPCODE)\n\t\treturn NULL;\n",
+               PackagePrefix[PackageIndex], PackagePrefix[PackageIndex]);
+       f_print(fout, "\treturn NULL;/*%d %s*/\n}\n",
+               PackageIndex, PackagePrefix[PackageIndex]);
+
        return;
     }
     f_print(fout, "int %s%sExecuteRequest(struct rx_call *z_call)\n",
@@ -2075,6 +2089,14 @@ er_ProcMainBody_setup(void)
     f_print(fout, "\treturn hton_syserr_conv(z_result);\n}\n");
 }
 
+static void
+er_HeadofOldStyleProc_setup2(void)
+{
+    if ( cflag ) {
+       f_print(fout, "int %sOpCodeIndex(int op)\n{\n", (combinepackages ? MasterPrefix : PackagePrefix[PackageIndex]));
+        f_print(fout, "\tswitch (op) {\n");
+    }
+}
 
 static void
 er_HeadofOldStyleProc_setup(void)
@@ -2144,6 +2166,44 @@ proc_er_case(definition * defp)
     f_print(fout, "\t\t\tbreak;\n");
 }
 
+static void
+proc_op_case(definition * defp)
+{
+    f_print(fout, "\t\tcase %d:", defp->pc.proc_opcodenum);
+    f_print(fout, "\treturn %d;\n",
+           defp->statindex);
+}
+
+static void
+er_BodyofOldStyleProc_setup2(void)
+{
+    list *listp;
+
+    if (!cflag)
+       return;
+    if (combinepackages) {
+       int temp = PackageIndex;
+       for (PackageIndex = 0; PackageIndex <= temp; PackageIndex++) {
+           for (listp = proc_defined[PackageIndex]; listp != NULL;
+                listp = listp->next)
+               proc_op_case((definition *) listp->val);
+       }
+       PackageIndex = temp;
+    } else {
+       for (listp = proc_defined[PackageIndex]; listp != NULL;
+            listp = listp->next)
+           proc_op_case((definition *) listp->val);
+    }
+}
+
+static void
+er_TailofOldStyleProc_setup2(void)
+{
+    if ( cflag ) {
+       f_print(fout, "\t\tdefault:\n");
+       f_print(fout, "\t\t\treturn -1;\n\t}\n}\n");
+    }
+}
 
 static void
 er_TailofOldStyleProc_setup(void)
@@ -2169,9 +2229,11 @@ h_ProcMainBody_setup(void)
 static void
 h_HeadofOldStyleProc_setup(void)
 {
+    char *pprefix = (combinepackages ? MasterPrefix :
+                    PackagePrefix[PackageIndex]);
+    f_print(fout,"\nstruct %sstats{\n\tint statsver;\n};", pprefix);
     f_print(fout,"\nextern int %s%sExecuteRequest(struct rx_call *);\n",
-           prefix,
-           (combinepackages ? MasterPrefix : PackagePrefix[PackageIndex]));
+           prefix, pprefix);
     f_print(fout,"\nextern int %sOpCodeIndex(int op);\n", PackagePrefix[PackageIndex]);
 }
 
index 7adb6f2..e003ef4 100644 (file)
@@ -225,5 +225,6 @@ struct definition {
     } def;
     procedure_def pc;
     int can_fail;
+    int statindex;
 };
 typedef struct definition definition;